# Welcome

## The official [Hedera Guardian](https://guardian.hedera.com/) documentation

The Hedera Guardian is an open-source platform for creating, managing, and issuing digital environmental assets such as carbon credits, renewable energy certificates, emission disclosures, and others on the Hedera network. It leverages a customizable workflow engine, calculation engine, verifiable-credential based identity management, and web3 technology to ensure transparent and fraud-proof operations, making it a key tool for transforming sustainability practices & environmental markets.

**The problem it solves**

Environmental markets depend on trust: trust that issued credits represent real and verifiable outcomes, that data hasn't been altered, and that the methodology behind a claim is sound. Today that trust is enforced through manual audits, closed registries, and siloed spreadsheets. Guardian makes it programmable — policies encode methodology rules directly, the Hedera Network provides an immutable audit trail, and verifiable credentials let any participant confirm the chain of custody without needing to trust a central intermediary. This helps to lower costs, improve speed and efficiency, and accelerate collaboration across domains such as finance, technology, and ecology.

**Platform at a glance**

Guardian is built around a number of core aspects and understanding how they relate is a good foundation to navigate the docs further.

* **Guardian Policies** are the rules of an environmental methodology — they can include data collection forms, role-based approval workflows, calculations, and dMRV endpoints — as executable software rather than PDF documents. A policy for Verra VM0047 specifies exactly what a project proponent submits, what a verifier approves, and how credits are calculated and issued.
* **Schemas** define the structure of every data submission within a policy — fields, types, and validation rules that make data submissions consistent and machine-readable.
* **Calculation Engine** powered by math blocks and formula linked definitions can be included inGuardian Policies. These are used to calculate emission reductions and application baselines, project, and net GHG emissions, applying leakage, uncertainty, and buffer-pool deductions, as well as converting verified results into credit quantities for token issuance.&#x20;
* **Tokens** are the digital environmental assets produced at key points within a policy workflow and represent outcomes recorded on the Hedera network as fungible or non-fungible tokens.
* **TrustChain** is the verifiable audit trail that links every token back to the original submissions, approvals, and calculations that produced it. Any participant can inspect the full chain of custody without relying on a central intermediary.
* **Standard Registry** is the platform role that publishes policies, onboards project participants, and manages credit issuance. It is the organizing entity for everything that happens in Guardian.
* **Methodology Library** is the world's largest open source repository of digitalized environmental methodologies. Anyone can download, import, inspect, test, and run these methodologies. The authoring process continues to be improved through global collaborations and feedback helping to bring costs down for all.

**Platform adopters and ecosystem**

Adoption of the Guardian has grown from an early concept in 2020 to a platform being used by dozens of companies in climate finance, including the world’s leading carbon standards, auditors, project developers, and enterprises. Ecosystem members have shared back 100+ open source contributors via GitHub, successfully issued numerous types of environmental assets, formed commercial partnerships, and developed the worlds largest open source methodology library. As you explore the platform, you'll notice mature capabilities developed in collaboration with a global ecosystem of stakeholders and community members — who we're grateful and proud of.

**Where to start**

| I want to…                            | Start here                                                                                       |
| ------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Understand how Guardian works         | Core Concepts                                                                                    |
| Install and run Guardian              | [Getting Started](/guardian/readme-1)                                                            |
| Create and publish policies           | [Standard Registry](/guardian/standard-registry)                                                 |
| Digitize an environmental methodology | [Methodology Digitization Handbook](/methodology-digitization/methodology-digitization-handbook) |
| Build on the Guardian API             | [API Reference](broken://spaces/EmXQ5yJXkOnwN84YXjVq)                                            |

**Open source community**

Establishing trust across climate and environmental markets is a hard, shared problem. No single organization can build the infrastructure that markets need on its own. Guardian exists because the problem requires open collaboration — on methodology digitalization, on verification standards, and technical workflows — to accelerate solutions to tough challenges.

Guardian is open source under the Apache 2.0 License and developed collaboratively by Hashgraph alongside carbon registries, auditors, project developers, governments, and enterprises building on the platform. Policies in the Methodology Library are contributed by organizations worldwide by registries, methodology authors, and independent developers.

Community calls, hands-on training sessions, and design workshops are regularly hosted. If you are building on the Guardian, digitizing a methodology, or improving the platform itself — contributions and feedback is welcome.

* [Contributing](/community-and-contributing/contributing)
* [Community Standards](/community-and-contributing/community-standards)
* [Methodology Library](https://github.com/hashgraph/guardian/tree/main/Methodology%20Library)
* [GitHub Milestones](https://github.com/hashgraph/guardian/milestones?sort=due_date\&direction=asc)
* [Share feedback or suggestions](mailto:guardian-feedback@hashgraph.com)

**Related**

* Concepts: Key Concepts
* Concepts: [Architecture](/guardian/architecture)
* Guide: [Methodology Digitization Handbook](/methodology-digitization/methodology-digitization-handbook)

***

*Guardian is open source under the Apache 2.0 License.*


# Getting Started

## **1. Introduction**

The Guardian is an open-source platform that streamlines the creation, management, and verification of digital environmental assets. It leverages a customizable Policy Workflow Engine and Web3 technology to ensure transparent and fraud-proof operations, making it a key tool for transforming sustainability practices & carbon markets.

Below are the universal software prerequisites, followed by network-specific items.

## 2. Prerequisites

### 2.1 Universal software

1. [**Git**](https://git-scm.com/downloads) – source-control tooling
2. [**Docker**](https://www.docker.com/) – one-command build & run (recommended)
3. [**MongoDB v6**](https://www.mongodb.com/), [**Node.js v24.15+**](https://nodejs.org/en/download), and [**NATS 2.9.25**](https://nats.io/) – auto-provisioned when using Docker Compose
4. [**IPFS storage**](https://docs.ipfs.tech/concepts/what-is-ipfs/) (choose one):
   * [**Storacha account**](https://storacha.network/) – IPFS pinning service (formerly Web3.Storage)
   * [**Filebase account**](https://filebase.com/) – S3-compatible IPFS pinning
   * Local IPFS node (e.g., [**Kubo**](https://github.com/ipfs/kubo)) – auto-provisioned when using Docker Compose
5. [**Valkey**](https://valkey.io) – in-memory cache & message broker (auto-provisioned by the Docker stack)

### 2.2 Hedera network

|              | Testnet (default)                                                     | Mainnet (production)                                                           |
| ------------ | --------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| **Account**  | Create via [Hedera Developer Portal](https://portal.hedera.com/login) | Create via Hedera-enabled wallet (e.g., [HashPack](https://www.hashpack.app/)) |
| **Key type** | ED25519                                                               | ED25519                                                                        |
| **Network**  | `testnet`                                                             | `mainnet`                                                                      |

> **Fees**: Mainnet operations incur HBAR costs—fund your account before running Guardian.

***

## 3. Preparing a Mainnet Account & Keys

1. Install a Hedera-enabled wallet (e.g., [HashPack](https://www.hashpack.app/)).
2. Create a Mainnet account and note the **Account ID** (`0.0.x`).
3. Export the **ED25519** key pair
   * *HashPack path*: **Settings → Manage Accounts → Export Private Key** (DER format).
4. Update your `.env`

   ```dotenv
   HEDERA_NET=mainnet
   HEDERA_OPERATOR_ID=0.0.123456
   HEDERA_OPERATOR_KEY=-----BEGIN PRIVATE KEY----- … -----END PRIVATE KEY-----
   ```

## 4. Preparing a Testnet Account & Keys

1. Create a Testnet account via the [Hedera Developer Portal](https://portal.hedera.com/login).
2. Record your **Account ID** (`0.0.x`).
3. Download the **ED25519** private key (ignore **ECDSA**)
   * Select **DER Encoded** — *do not* choose *HEX Encoded*.
4. Update your `.env`

   ```dotenv
   HEDERA_NET=testnet
   HEDERA_OPERATOR_ID=0.0.987654
   HEDERA_OPERATOR_KEY=-----BEGIN PRIVATE KEY----- … -----END PRIVATE KEY-----
   ```

## 5. Installation

1. **Docker-Compose**

   ```bash
   docker compose -f ./deploy/docker-compose.yml --profile all up -d
   ```

   *(Detects Testnet/Mainnet from `.env`)*
2. **Pre-built containers** — pull `hashgraph/guardian:latest` and supply `.env` as a secret.
3. **Manual build** — clone repo, install Node deps, compile, start services.

## **6. Troubleshooting**

* **Server not starting?** Ensure that Docker is running and all containers are up.
* **Cannot access the admin dashboard?** Check if the correct ports (3000) are open and not blocked by your firewall.
* **Issues with API calls?** Verify that your Hedera account ID and private key are correctly configured in the `.env` file.
* For additional help, visit the [Hedera Guardian GitHub Issues](https://github.com/hashgraph/guardian/issues).

## **7. Additional Resources**

* [Hedera Guardian Documentation](https://guardian.hedera.com)
* [Hedera Developer Portal](https://portal.hedera.com/login)
* [Roadmap](/community-and-contributing/roadmap)
* [Youtube Channel](https://www.youtube.com/@envisionblockchain/featured)

## **8. Feedback and Support**

* Please send feedback, feature, and support requests to [guardian-feedback@hashgraph.com](mailto:guardian-feedback@hashgraph.com?subject=Re:%20Hedera%20Guardian%20Feedback%20or%20Request\&body=This%20is%20%5Bfeedback%20%7C%20support%20request%20%7C%20feature%20request%5D%0A%0A--%0A%0AAdd%20a%20summary%20here.)
* You can also open issues and feature requests in the [GitHub repository](https://github.com/hashgraph/guardian/issues).

## **9. Legal and Licensing**

* Hedera Guardian is open-source and licensed under the Apache 2.0 License. Please review the [LICENSE](https://github.com/hashgraph/guardian/blob/develop/LICENSE/README.md) file for more details.


# Discovering Environmental assets on Hedera

As identified in Hedera Improvement Proposal 19 (HIP-19), each entity on the Hedera network may contain a specific identifier in the memo field for discoverability. Guardian demonstrates this when every Hedera Consensus Service transaction is logged to a Hedera Consensus Service Topic. Observing the Hedera Consensus Service Topic, you can discover newly minted tokens. In the memo field of each token mint transaction you will find a unique Hedera message timestamp. This message contains the url of the Verifiable Presentation (VP) associated with the token. The VP can serve as a starting point from which you can traverse the entire sequence of documents produced by Guardian policy workflow, which led to the creation of the token. Please see p.17 in the [FAQ](https://docs.hedera.com/guardian/faqs/) for more information. This is further defined in [Hedera Improvement Proposal 28 (HIP-28)](https://hips.hedera.com/hip/hip-28).


# Guardian Glossary

| Term                                     | Definition                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| W3C Decentralized Identifier             | W3C Decentralized Identifiers (DIDs) are a new type of identifier that enables verifiable, decentralized digital identity. A DID refers to any subject (e.g., a person, organization, thing, data model, abstract entity, etc.) as determined by the controller of the DID. DIDs are URIs that associate a DID subject with a DID document allowing trustable interactions associated with that subject.                                        |
| W3C DID Document                         | A W3C DID Document expresses cryptographic material, verification methods, or services, which provide a set of mechanisms enabling a DID controller to prove control of the DID. Services enable trusted interactions associated with the DID subject.                                                                                                                                                                                          |
| W3C Verifiable Credential                | A W3C Verifiable Credential is a set of tamper-evident claims and metadata that cryptographically prove who issued it.                                                                                                                                                                                                                                                                                                                          |
| Credential Issuer                        | An entity that issues a W3C Verifiable Credential                                                                                                                                                                                                                                                                                                                                                                                               |
| Credential Holder                        | An entity in possession of a W3C Verifiable Credential. Note, the Credential Holder does not have to be the subject of the claims in the W3C Verifiable Credential.                                                                                                                                                                                                                                                                             |
| Credential Verifier                      | An entity that cryptographically and schematically verifies the conformance of a W3C Verifiable Credential with the W3C Verifiable Credential standard.                                                                                                                                                                                                                                                                                         |
| W3C Verifiable Presentation              | A Verifiable Presentation expresses data from one or more verifiable credentials, and is packaged in such a way that the authorship of the data is verifiable. If verifiable credentials are presented directly, they become verifiable presentations. Data formats derived from verifiable credentials that are cryptographically verifiable, but do not of themselves contain verifiable credentials, might also be verifiable presentations. |
| Policy Workflow Engine                   | Manages and monitors the state of required policy actions and the required information flow in a policy grouped into a policy workflow, and further determines which are the next policy actions based on the state of a policy workflow. The policy actions may be anything from saving an application form in a document management system to sending a reminder e-mail to users or escalating overdue items to management.                   |
| Policy Workflow                          | The execution of a series of causally connected and deterministic policy actions where the policy workflow or policy action participants are grouped into one or more workgroups that are attached to policy action of a policy workflow.                                                                                                                                                                                                       |
| Policy Action                            | One or more deterministic policy rules applied to the input of a policy action request producing an output of the policy action in the form of a state transition.                                                                                                                                                                                                                                                                              |
| Policy Workflow Group                    | A group of entities participating in a policy workflow.                                                                                                                                                                                                                                                                                                                                                                                         |
| Policy Workflow State Object             | A data object associated with a request for a Policy Action within a given Policy Workflow submitted by a participant in the Policy Workflow Group representing the state of the submitted request.                                                                                                                                                                                                                                             |
| Policy Action Request                    | Request for the execution a Policy Action on a Policy Workflow State Object within a given Policy Workflow submitted by a participant in the Policy Workflow Group using a Policy State Machine                                                                                                                                                                                                                                                 |
| Policy State Machine                     | A technical execution framework calculating the state transition of a Policy Workflow State Object based on a Policy Action Request and the relevant Policy Action instance.                                                                                                                                                                                                                                                                    |
| Policy State Machine Execution Framework | A set of rules allowing for a deterministic computation of a state transition of a Policy Workflow State Object through a Policy Action within a Policy Workflow                                                                                                                                                                                                                                                                                |


# Installation Guide

To get a local copy up and running quickly, follow the steps below. Please refer to [https://guardian.hedera.com](https://guardian.hedera.com/) for complete documentation.


# Prerequisites

## 1. Universal Software

1. [**Git**](https://git-scm.com/downloads) – source-control tooling
2. [**Docker**](https://www.docker.com/) – one-command build & run (recommended)
3. [**MongoDB v6**](https://www.mongodb.com/), [**Node.js v24.15+**](https://nodejs.org/en/download), and [**NATS 2.9.25**](https://nats.io/) – auto-provisioned when using Docker Compose
4. [**IPFS storage**](https://docs.ipfs.tech/concepts/what-is-ipfs/) (choose one):
   * [**Storacha account**](https://storacha.network/) – IPFS pinning service (formerly Web3.Storage)
   * [**Filebase account**](https://filebase.com/) – S3-compatible IPFS pinning
   * Local IPFS node (e.g., [**Kubo**](https://github.com/ipfs/kubo)) – auto-provisioned when using Docker Compose
5. [**Valkey**](https://valkey.io) – in-memory cache & message broker (auto-provisioned by the Docker stack)

When building reference implementation, you can manually build every component or run a single command with Docker.

{% hint style="info" %}
**Note**: If you have already installed another version of Guardian, remember to **perform backup operation before upgrading**.
{% endhint %}

## 2. Hedera Network

|              | Testnet (default)                                                     | Mainnet (production)                                                           |
| ------------ | --------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| **Account**  | Create via [Hedera Developer Portal](https://portal.hedera.com/login) | Create via Hedera-enabled wallet (e.g., [HashPack](https://www.hashpack.app/)) |
| **Key type** | ED25519                                                               | ED25519                                                                        |
| **Network**  | `testnet`                                                             | `mainnet`                                                                      |

> **Fees**: Mainnet operations incur HBAR costs—fund your account before running Guardian.

## 3. Automatic Installation

### 3.1 Prerequisites for Automatic Installation

* [**Docker**](https://www.docker.com/)

#### 3.1.1 Docker Installation

If you build with docker [MongoDB](https://www.mongodb.com), [NodeJS](https://nodejs.org) and [Nats](https://nats.io/) will be installed and configured automatically.


# Installation

There are multiple ways to install Guardian:

1. [Using Docker](/guardian/readme-1/getting-started/installation/building-from-source-and-run-using-docker)
2. [Pre-Build Containers](/guardian/readme-1/getting-started/installation/building-from-pre-build-containers)
3. [Manually](/guardian/readme-1/getting-started/installation/build-executables-and-run-manually)


# Building from source and run using Docker

[Step By Step Process](#step-by-step-process)

[Demo Video](#demo-video)

[Troubleshoot](#troubleshoot)

### Step By Step Process

The following steps need to be executed in order to start Guardian using docker:

1. [Clone the repo](#id-1.-clone-the-repo)
2. [Configure project level .env file](#id-2.-configure-project-level-.env-file)
3. [Update BC access variables](#id-3.-update-bc-access-variables)
4. [Setup IPFS](#id-4.-setup-ipfs)
5. [Setting up ChatGPT Key (if required)](#id-5.-setting-up-chat-gpt-api-key-to-enable-ai-search-and-guided-search)
6. [Build and launch with Docker](#id-6.-build-and-launch-with-docker)
7. [Browse to http://localhost:3000](#id-7.-browse-the-local-browser)
8. [For increased security remove credentials from `.env` file](#id-8.-increase-security)

## 1. Clone the repo

```shell
git clone https://github.com/hashgraph/guardian.git
```

## 2. Configure project level .env file.

The main configuration file that needs to be provided to the Guardian system is the `.env` file. Note that these files contain sensitive configuration such as keys and access credentials which are only used at the initial start of Guardian. For increased security it is recommended to disable inbound network access until after the first run of Guardian, when the credentials configuration has been removed from `.env` file (see p8 below).

For this example purpose let's name the Guardian platform as "develop"

```shell
   GUARDIAN_ENV="develop"
```

{% hint style="info" %}
**Note** Every single service is provided in its folder with a `.env.template` file, this set of files are only needed for the case of Manual installation.
{% endhint %}

## 3. Update BC access variables

Update the following files with your Hedera Mainnet or Testnet account info (see prerequisites) as indicated. Please check complete steps to generate Operator\_ID and Operator\_Key by looking at the link: [How to Create Operator\_ID and Operator\_Key](https://docs.hedera.com/guardian/getting-started/getting-started/how-to-create-operator-id-and-operator-key). The Operator\_ID and Operator\_Key and HEDERA\_NET are all that Guardian needs to access the Hedera Blockchain assuming a role on it. This parameters needs to be configured in a file at the path `./configs`, the file should use the following naming convention:

`./configs/.env.\<GUARDIAN_ENV\>.guardian.system`

There will be other steps in the Demo Usage Guide that will be required for the generation of Operator\_ID and Operator\_Key. It is important to mention that the Operator\_ID and Operator\_Key in the `./configs/.env.<GUARDIAN_ENV>.guardian.system` will be used to generate demo accounts.

The parameter `HEDERA_NET` may assume the following values: `mainnet`, `testnet`, `previewnet`, `localnode`. choose the right value depending on your target Hedera network on which the `OPERATOR_ID` has been defined.

As examples:

following the previous example, the file to configure should be named: `./configs/.env.develop.guardian.system`, this file is already provided in the folder as example, only update the variables OPERATOR\_ID, OPERATOR\_KEY and HEDERA\_NET.

```plaintext
OPERATOR_ID="..."
OPERATOR_KEY="..."
HEDERA_NET="..."
```

Starting from Multi-environment release (2.13.0) it has been introduced a new parameter `PREUSED_HEDERA_NET`. Multienvironemnt is a breaking change and the configuration of this parameter intend to smooth the upgrading. `PREUSED_HEDERA_NET` configuration depends on the installation context.

* If the installation is a completely new one just remove the parameter and feel free to jump to the next paragraph.
* if you are upgrading from a release after the Multi-environment (>= to 2.13.0) do not change the state of this parameter (so if you removed the parameter in some previous installation do not introduce it).
* if the installation is an upgrading from a release previous of the Multi-environment (<= to 2.13.0) to a following one you need to configure the `PREUSED_HEDERA_NET`. After that the parameter will last in the configuration unchanged.

### 3.1. PREUSED\_HEDERA\_NET configuration

The `PREUSED_HEDERA_NET` parameter is intended to hold the target Hedera network that the system already started to notarize data to. PREUSED\_HEDERA\_NET is the reference to the HEDERA\_NET that was in usa before the upgrade. To let the Multi-environment transition happen in a transparent way the `GUARDIAN_ENV` parameter in the `.env` file has to be configured as empty while the `PREUSED_HEDERA_NET` has to be set with the same value configured in the `HEDERA_NET` parameter in the previous configuration file.

`PREUSED_HEDERA_NET` never needs to be changed after the first initialization. On the contrary it will be possible to change `HEDERA_NET` to dials with all the Hedera different networks.

* as first Example:

in case of the upgrading from a release minor then 2.13.0 to a bigger one and keep using the same HEDERA\_NET="Mainnet"(as example)

configure the name the Guardian platform as empty in the `.env` file

```shell
   GUARDIAN_ENV=""
```

In this case the configuration is stored in the file named: `./configs/.env..guardian.system`, and is already provided in the folder as example, update the variables OPERATOR\_ID and OPERATOR\_KEY.

```plaintext
OPERATOR_ID="..."
OPERATOR_KEY="..."
```

PREUSED\_HEDERA\_NET is the reference to your previous HEDERA\_NET configuration then you should set its value to match your previous HEDERA\_NET configuration.

```plaintext
HEDERA_NET="mainnet"
PREUSED_HEDERA_NET="mainnet"
```

because you are keeping on using HEDERA\_NET as it was pointing to the "mainnet" in the previous installation too.

* As a second example: to test the new release change the HEDERA\_NET to "testnet". This is the complete configuration:

Set the name of the Guardian platform to whatever descripting name in the `.env` file

```shell
   GUARDIAN_ENV="testupgrading"
```

In this case the configuration is stored in the file named: `./configs/.env.testupgrading.guardian.system` again update the variables OPERATOR\_ID and OPERATOR\_KEY using your testnet account.

```plaintext
OPERATOR_ID="..."
OPERATOR_KEY="..."
```

set the HEDERA\_NET="testnet" and set the PREUSED\_HEDERA\_NET to refer to the mainnet as you wish that Mainet data remains unchanged.

```plaintext
HEDERA_NET="testnet"
PREUSED_HEDERA_NET="mainnet"
```

This configuration allows you to leave untouched all the data referring to Mainnet in the Database while testing on Testnet. Refer to Guardian [documentation](https://docs.hedera.com/guardian/guardian/readme/environments/multi-session-consistency-according-to-environment) for more details.

{% hint style="info" %}
**Note**. You can use the Schema Topic ID (`INITIALIZATION_TOPIC_ID`) already present in the configuration files, or you can specify your own.
{% endhint %}

{% hint style="info" %}
**Note** for any other GUARDIAN\_ENV name of your choice just copy and paste the file `/configs/.env.template.guardian.system` and rename as `/configs/.env.<choosen name>.guardian.system`
{% endhint %}

### 3.2 Setting up JWT keys in /`.env` file

To start of auth-service it is necessary to fill in `JWT_PRIVATE_KEY` and `JWT_PUBLIC_KEY`, which are RSA key pair. You can generate it in any convenient way, for example, using this service <https://travistidwell.com/jsencrypt/demo/>.

<figure><img src="/files/jQ0a0hz4OTRIyO2X97Yg" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Note: **Please make sure you copy and paste complete keys starting from "-----BEGIN-----" to "-----END-----".**
{% endhint %}

To start all services, you need to create a 2048-bit RSA key pair for each service. You can generate a key pair in any convenient way—for example, using the online tool at <https://mkjwk.org/> with the following settings:\
\- key size: 2048\
\- key use: signature\
\- algorithm: RS256: RSA\
\- key ID: sha256\
\- show: yes

<figure><img src="/files/uMl4cBHcyuGvsj72nqyH" alt=""><figcaption></figcaption></figure>

For each service, you must add its secret key \`SERVICE\_JWT\_SECRET\_KEY\` and a list of all public keys from every service:\
\- \`SERVICE\_JWT\_PUBLIC\_KEY\_WORKER\_SERVICE\`\
\- \`SERVICE\_JWT\_PUBLIC\_KEY\_TOPIC\_LISTENER\_SERVICE\`\
\- \`SERVICE\_JWT\_PUBLIC\_KEY\_QUEUE\_SERVICE\`\
\- \`SERVICE\_JWT\_PUBLIC\_KEY\_POLICY\_SERVICE\`\
\- \`SERVICE\_JWT\_PUBLIC\_KEY\_NOTIFICATION\_SERVICE\`\
\- \`SERVICE\_JWT\_PUBLIC\_KEY\_LOGGER\_SERVICE\`\
\- \`SERVICE\_JWT\_PUBLIC\_KEY\_GUARDIAN\_SERVICE\`\
\- \`SERVICE\_JWT\_PUBLIC\_KEY\_AUTH\_SERVICE\`\
\- \`SERVICE\_JWT\_PUBLIC\_KEY\_API\_GATEWAY\_SERVICE\`\
\- \`SERVICE\_JWT\_PUBLIC\_KEY\_AI\_SERVICE\`

**Note:** Alternatively, you can create a single key pair and, instead of adding the public keys for each individual service, you can add \`SERVICE\_JWT\_SECRET\_KEY\_ALL\` and \`SERVICE\_JWT\_PUBLIC\_KEY\_ALL\` to use the same keys for all services. However, it is recommended to generate a separate key pair for each service.

<figure><img src="/files/KDKSuj00EyWc1poSF8KP" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
**Note**: It is important to add these keys to the env files, because without them the services will return errors, and communication with a service that does not sign messages for the message queue will not be supported.
{% endhint %}

{% hint style="info" %}
Note: Please use the appropriate Private Key and Public Key as shown in the above image.
{% endhint %}

## 4. Setup IPFS

Now, we have four options to setup IPFS node : 1. Local node 2. IPFS Web3Storage node. 3. IPFS Filebase Bucket. 4. Custom IPFS

### 4.1 Setting up IPFS Local node:

* 4.1.1 We need to install and configure any IPFS node. [example](https://github.com/yeasy/docker-ipfs)
* 4.1.2 For setup IPFS local node you need to set variables in the same file `./configs/.env.develop.guardian.system`

```
IPFS_NODE_ADDRESS="..." # Default IPFS_NODE_ADDRESS="http://ipfs-node:5001"
IPFS_PUBLIC_GATEWAY='...' # Default IPFS_PUBLIC_GATEWAY='http://ipfs-node:8080/ipfs/{cid}'
IPFS_PROVIDER="local"
```

{% hint style="info" %}
Note:

1. Default IPFS\_NODE\_ADDRESS="<http://ipfs-node:5001>"
2. Default IPFS\_PUBLIC\_GATEWAY="[http://ipfs-node:8080/ipfs/${cid}](http://ipfs-node:8080/ipfs/$%7Bcid%7D%22)"
   {% endhint %}

### 4.2 Setting up IPFS Web3Storage node:

For setup IPFS web3storage node you need to set variables in file `./configs/.env..guardian.system`:

```
IPFS_PROVIDER="web3storage"
```

To configure access to the [w3up](https://github.com/web3-storage/w3up) IPFS upload API from web3.storage for your Guardian instance you need to set correct values to the following variables in the `./configs/.env.<environment>.guardian.system` file.

```
IPFS_STORAGE_KEY="..."
IPFS_STORAGE_PROOF="..."
```

To know complete process of How to setup IPFS Storage variables, please check [How to generate Web3.Storage API values](/guardian/readme-1/getting-started/how-to-generate-web3.storage-api-key)

### 4.3 Setting up IPFS Filebase Bucket:

To configure the Filebase IPFS provider, set the following variables in the file `./configs/.env.<environment>.guardian.system`**:**

```
IPFS_STORAGE_API_KEY="Generated Firebase Bucket Token"
IPFS_PROVIDER="filebase"
```

Create a new "bucket" on Filebase since we utilize the **IPFS Pinning Service API Endpoint** service. The **token** generated for a bucket corresponds to the **IPFS\_STORAGE\_API\_KEY** environment variable within the guardian's configuration.

For detailed setup instructions, refer to the official <https://docs.filebase.com/api-documentation/ipfs-pinning-service-api>.

### **4.4 Implement and test a custom IPFS provider:**

We provide a flexible workflow for integrating additional IPFS providers:

* Configure your environment variables under "configs/".
* In the "worker-service" directory, execute `yarn test:ipfs` to:
  * Build the project within the directory.
  * Run tests to verify the validity of your configuration without needing to build the entire Guardian system.
* To add a new provider, extend the "IpfsProvider" enum in the "ipfs-client" with your provider's enum value and implement your logic following the given examples. Consider the following recommendations:

  * Design your logic based on interfaces for greater simplicity and maintainability ***(This requires more work in v2.20.x)***.
  * Ensure that a custom validator for your new client is present in the "worker-service".
  * Test iteratively by running `yarn test:ipfs` in the "worker-service" directory until your client is fully functional with your desired configuration.

  This streamlined process allows any product team to swiftly integrate new IPFS clients into the Guardian system, significantly reducing development time

## 5. Setting up Chat GPT API KEY to enable AI Search and Guided Search:

For setting up AI and Guided Search, we need to set OPENAI\_API\_KEY variable in `./configs/.env*` files.

```
OPENAI_API_KEY="..."
```

## 6. Build and launch with Docker.

Make sure you use Docker Compose V2 (comes with Docker Desktop > 3.6.0) as at <https://docs.docker.com/compose/install/>. Please note that this build is meant to be used in production and will not contain any debug information. From the project's root folder:

```
docker-compose up -d --build
```

{% hint style="info" %}
**Note:**

About docker-compose: from the end of June 2023 Compose V1 won’t be supported anymore and will be removed from all Docker Desktop versions. Make sure you use Docker Compose V2 (comes with Docker Desktop > 3.6.0) as at <https://docs.docker.com/compose/install/>
{% endhint %}

## 7. Browse the local browser

Browse to <http://localhost:3000> and complete the setup. To get more info, please check: [Launching Guardian](/guardian/readme-1/getting-started/installation/launching-guardian)

## 8. Increase security

For increased security remove credentials from `.env` file and enable network access

On first state the credentials from `.env` file are copied into the secure storage as configured (e.g. Vault). After that Guardian does not use any credentials stored in the .env file, thus they should be removed for security reasons.

### Process on How to Configure SSL Encryption:

1. Install <https://github.com/FiloSottile/mkcert> utility
2. Navigate to `certs` folder and execute

```
mkcert -install
mkcert -cert-file server-cert.pem -key-file server-key.pem localhost ::1
mkcert -client -cert-file client-cert.pem -key-file client-key.pem localhost ::1 email@localhost
```

3. Edit `configs/nats.conf` and uncomment the `tls` section
4. Set `TLS_NATS` variable to `true` (edited)

### Demo Video

[Youtube](https://www.youtube.com/watch?v=3fXm7wAERPM\&list=PLnld0e1pwLhqdR0F9dusqILDww6uZywwR\&index=1)

### Troubleshoot

#### To delete all the Docker Containers

```
docker builder prune --all
```

#### To run by cleaning Docker Cache

```
docker-compose build --no-cache
```

In the subsection you’ll find the following examples:

* [Steps on how to deploy Guardian using a default Environment](/guardian/readme-1/getting-started/installation/building-from-source-and-run-using-docker/deploying-guardian-using-default-environment)
* [Steps on how to deploy Guardian using a default Environment ( Develop )](/guardian/readme-1/getting-started/installation/building-from-source-and-run-using-docker/deploying-guardian-using-a-specific-environment-develop)
* [Steps on how to deploy Guardian using a default Environment ( QA )](/guardian/readme-1/getting-started/installation/building-from-source-and-run-using-docker/deploying-guardian-using-a-specific-environment-qa)


# Deploying Guardian using default Environment

The following steps will describe on how to deploy Guardian using the default Environment:

**Step 1:**

By default GUARDIAN\_ENV="" is Blank in the .env.template

Create .env file and leave the variable as Empty

<pre><code><strong>GUARDIAN_ENV=""
</strong></code></pre>

{% hint style="info" %}
**Note : If you forget to create the .env file , the docker compose will evaluate the variable as Empty, giving a warning, but the end result will be the same.**
{% endhint %}

**Step 2:**

Select the `.env..guardian.system` file which is already provided as in example inside configs Directory at the root level.

```
/configs/.env..guardian.system
```

**Step 3:**

Set **OPERATOR\_ID** , **OPERATOR\_KEY** and **IPFS\_STORAGE\_API\_KEY** in the `.env..guardian.system` file inside configs Directory at the root level.

**Step 4:**

Run

```
docker-compose up -d --build
```

Wait until all the services are started.

**Step 5:**

Launch [localhost:3000](http://localhost:3000/)


# Deploying Guardian using a specific Environment ( DEVELOP )

The following steps will describe on how to deploy Guardian using the default Environment (Develop):

**Step 1:**

Create the .env file Set the GUARDIAN\_ENV="develop" in the .env file ( Refer .env.template as example)

<pre><code><strong>GUARDIAN_ENV="develop"
</strong></code></pre>

**Step 2:**

Select the `.env.develop.guardian.system` file which is already provided as in example inside configs Directory at the root level.

```
/configs/.env.develop.guardian.system
```

**Step 3:**

Set **OPERATOR\_ID** , **OPERATOR\_KEY** and **IPFS\_STORAGE\_API\_KEY** in the `.env.develop.guardian.system` file inside configs Directory at the root level

**Step 4:**

Run

```
docker-compose up -d --build
```

Wait until all the services are started.

**Step 5:**

Launch [localhost:3000](http://localhost:3000/)


# Deploying Guardian using a specific Environment (QA)

The following steps will describe on how to deploy Guardian using the default Environment (QA):

**Step 1:**

Create the .env file

Set the GUARDIAN\_ENV="qa" in the .env file ( Refer .env.template as example)

<pre><code><strong>GUARDIAN_ENV="qa"
</strong></code></pre>

**Step 2 :**

Create `.env.qa.guardian.system` file inside configs Directory at the root level. ( Refer .env.template.guardian.system as example)

```
/configs/.env.qa.guardian.system
```

**Step 3:**

Set **OPERATOR\_ID** , **OPERATOR\_KEY** and **IPFS\_STORAGE\_API\_KEY** in the `.env.qa.guardian.system` file inside configs Directory at the root level

**Step 4:**

Run

```
docker-compose up -d --build
```

Wait until all the services are started.

**Step 5:**

Launch [localhost:3000](http://localhost:3000/)


# Building from Pre-build containers

#### Docker compose configuration for apple M1 using images:

```
version: "3.8"
services:
  mongo:
    image: mongo
    command: "--setParameter allowDiskUseByDefault=true"
    restart: always
    expose:
      - 27017
 
  message-broker:
    image: nats:2.10.9
    expose:
      - 4222
    ports:
      - '8222:8222'
    command: '--http_port 8222'

  mongo-express:
    image: mongo-express:1.0.0-alpha.4
    ports:
      - 8081
    environment:
      ME_CONFIG_MONGODB_SERVER: mongo
      ME_CONFIG_MONGODB_PORT: 27017
      ME_CONFIG_SITE_BASEURL: /mongo-admin
    depends_on:
      - mongo


  notification-service:
    env_file:
      - ./configs/.env.${GUARDIAN_ENV}.guardian.system
    image: gcr.io/hedera-registry/notification-service:2.22.0
    platform: linux/amd64
    depends_on:
      - message-broker

 
  logger-service:
    env_file:
      - ./configs/.env.${GUARDIAN_ENV}.guardian.system
    image: gcr.io/hedera-registry/logger-service:2.22.0
    platform: linux/amd64
    depends_on:
      - message-broker
 
  worker-service-1:
    env_file:
      - ./configs/.env.${GUARDIAN_ENV}.guardian.system
    image: gcr.io/hedera-registry/worker-service:2.22.0
    platform: linux/amd64
    depends_on:
      - auth-service
    environment:
      SERVICE_CHANNEL: 'worker.1'
      IPFS_STORAGE_KEY: "..." 
      IPFS_STORAGE_PROOF: "..."
 
  worker-service-2:
    env_file:
      - ./configs/.env.${GUARDIAN_ENV}.guardian.system
    image: gcr.io/hedera-registry/worker-service:2.22.0
    platform: linux/amd64
    depends_on:
      - auth-service
    environment:
      SERVICE_CHANNEL: 'worker.2'
      IPFS_STORAGE_KEY: "..." 
      IPFS_STORAGE_PROOF: "..."
 
  auth-service:
    env_file:
      - ./configs/.env.${GUARDIAN_ENV}.guardian.system
    image: gcr.io/hedera-registry/auth-service:2.22.0
    platform: linux/amd64
    depends_on:
      - mongo
      - message-broker
      - logger-service
 
  api-gateway:
    env_file:
      - ./configs/.env.${GUARDIAN_ENV}.guardian.system
    image: gcr.io/hedera-registry/api-gateway:2.22.0
    platform: linux/amd64
    expose:
      - 3002
    depends_on:
      - mongo
      - message-broker
      - guardian-service
      - auth-service
      - logger-service
 
  policy-service:
    env_file:
      - ./configs/.env.${GUARDIAN_ENV}.guardian.system
    image: gcr.io/hedera-registry/policy-service:2.22.0
    platform: linux/amd64
    depends_on:
      - mongo
      - message-broker
      - auth-service
      - logger-service
      
  mrv-sender:
    env_file:
      - ./configs/.env.${GUARDIAN_ENV}.guardian.system
    image: gcr.io/hedera-registry/mrv-sender:2.22.0
    platform: linux/amd64
  
  topic-viewer:
    env_file:
      - ./configs/.env.${GUARDIAN_ENV}.guardian.system
    image: gcr.io/hedera-registry/mrv-sender:2.22.0
    platform: linux/amd64
  
  guardian-service:
    env_file:
      - ./configs/.env.${GUARDIAN_ENV}.guardian.system
    image: gcr.io/hedera-registry/guardian-service:2.22.0
    platform: linux/amd64
    depends_on:
      - mongo
      - message-broker
      - auth-service
      - logger-service
      - worker-service-1
      - worker-service-2
      - policy-service
    environment:
      OPERATOR_ID: "..."
      OPERATOR_KEY: "..."
      
  
  web-proxy:
    image: gcr.io/hedera-registry/frontend:2.22.0
    platform: linux/amd64
    environment:
      GATEWAY_HOST: 'api-gateway'
      GATEWAY_PORT: '3002'
      GATEWAY_CLIENT_MAX_BODY_SIZE: '1024m'
    ports:
      - "3000:80"
    depends_on:
      - guardian-service
      - auth-service
      - api-gateway
      - mrv-sender
      - mongo-express
volumes:
  mongo:
  # volume-guardian-service:
  # volume-ui-service:
  # volume-mrv-sender:
  #  volume-message-broker:
```


# Build executables and run manually

If you want to manually build every component with debug information, then build and run the services and packages in the following sequence: Interfaces, Logger Helper, Message Broker, Logger Service, Auth Service, IPFS, Guardian Service, UI Service, and lastly, the MRV Sender Service. See below for commands.

### Prerequisites for Manual Installation

* [MongoDB](https://www.mongodb.com/) ,
* [NodeJS](https://nodejs.org/)
* [Yarn](https://yarnpkg.com/getting-started/install)
* [Nats](https://nats.io/)

#### Build and start each component

Install, configure and start all the prerequisites, then build and start each component.

#### Services Configuration:

* for each of the services create the file `./<service_name>/.env` to do this copy, past and rename the file `./<service_name>/.env.template`

  For example:

  in `./guardian-service/.env`:

  ```plaintext
      GUARDIAN_ENV="develop"
  ```

  If need to configure OVERRIDE uncomment the variable in file `./guardian-service/.env`:

  ```plaintext
      OVERRIDE="false"
  ```
* configure the file `./<service_name>/configs/.env.<service>.<GUARDIAN_ENV>` file: to do this copy, past and rename the file `./<service_name>/.env.<service>.template`

  following previous example:

  in `./guardian-service/configs/.env.guardian.develop`:

```plaintext
OPERATOR_ID="..."
OPERATOR_KEY="..."
```

* Setting up Chat GPT API KEY to enable AI Search and Guided Search:

  For setting up AI and Guided Search, we need to set OPENAI\_API\_KEY variable in `./ai-service/configs/.env*` files.

  ```
  OPENAI_API_KEY="..."
  ```

***NOTE:*** Once you start each service, please wait for the initialization process to be completed.\*\*

1. Clone the repo

```
git clone https://github.com/hashgraph/guardian.git
```

2. Install dependencies

```
yarn
```

3. Build ***@guardian/interfaces*** package

```
 yarn workspace @guardian/interfaces run build
```

4. Build ***@guardian/common*** package

```
yarn workspace @guardian/common run build
```

5. Build and start ***logger-service*** service

To build the service:

```
 yarn workspace logger-service run build
```

Configure the service as previously described. Do not need special variables configuration.

To start the service:

```
yarn workspace logger-service start
```

6. Build and start ***auth-service*** service

To build the service:

```
yarn workspace auth-service run build
```

Configure the service as previously described. Do not need special variables configuration.

To start the service:

```
yarn workspace auth-service start
```

{% hint style="info" %}
**Note:** For correct start of auth-service it is necessary to fill in JWT\_PRIVATE\_KEY and JWT\_PUBLIC\_KEY, which are RSA key pair. You can generate it in any convenient way, for example, using this service <https://travistidwell.com/jsencrypt/demo/>.
{% endhint %}

{% hint style="info" %}
**Note:** For password validation used 2 variables MIN\_PASSWORD\_LENGTH and PASSWORD\_COMPLEXITY.\
MIN\_PASSWORD\_LENGTH sets the minimum password length. Default value is 8, minimum value is 1.\
PASSWORD\_COMPLEXITY sets the password complexity level. Available values: easy, medium, hard

* easy: no rules
* medium: one uppercase letter, one lowercase letter, one number
* hard: one uppercase letter, one lowercase letter, one number, one special character

Default value is medium
{% endhint %}

7. Build and start ***policy-service*** service

To build the service:

```
yarn workspace policy-service run build
```

Configure the service as previously described. Do not need special variables configuration.

To start the service:

```
yarn workspace policy-service start
```

8. Build and start ***worker-service*** service To build the service:

```
yarn workspace worker-service run build
```

Configure the service as previously described. Update **IPFS\_STORAGE\_API\_KEY** value in `./worker-service/configs/.env.worker` file.

To start the service:

```
yarn workspace worker-service start
```

9. Build and start **notification*****-service*** service

To build the service:

Yarn:

```
yarn workspace notification-service run build
```

Npm:

```
npm --workspace=notification-service run build
```

Configure the service as previously described. Update **OPERATOR\_ID** and **OPERATOR\_KEY** values in `./guardian-service/configs/.env.worker` file as in the example above.

To start the service (found on [http://localhost:3002](http://localhost:3002/)):

Yarn:

```
yarn workspace notification-service start
```

Npm:

```
npm --workspace=notification-service start
```

10. Build and start ***guardian-service*** service

To build the service:

```
yarn workspace guardian-service run build
```

Configure the service as previously described. Update **OPERATOR\_ID** and **OPERATOR\_KEY** values in `./guardian-service/configs/.env.worker` file as in the example above.

To start the service (found on [http://localhost:3002](https://localhost:3002)):

```
 yarn workspace guardian-service start
```

11. Build and start ***api-gateway*** service

To build the service:

```
yarn workspace api-gateway run build
```

Configure the service as previously described. Do not need special variables configuration.

To start the service (found on [http://localhost:3002](https://localhost:3002)):

```
yarn workspace api-gateway start
```

12. From the **mrv-sender** folder

To build the service:

```
npm install
npm run build
```

Configure the service as previously described. Do not need special variables configuration.

To start the service (found on <http://localhost:3005>):

```
npm start
```

13. **From the ai-service folder**

To build the service:

Yarn:

```
yarn workspace ai-service run build
```

Npm:

```
npm --workspace=ai-service run build
```

Configure the service as previously described. Do not need special configuration variables.

Yarn:

```
yarn workspace ai-service start
```

Npm:

```
npm --workspace=ai-service start
```

14. From the **frontend** folder

To build the service:

```
npm install
npm run build
```

To start the service (found on <http://localhost:4200>)

```
npm start
```

Browse to <http://localhost:3000> and complete the setup. To get more info, please check: [Launching Guardian](/guardian/readme-1/getting-started/installation/launching-guardian)


# Cloud Deployment

This document describes how to deploy a guardian instance on one of the three major cloud providers using Kubernetes.

This document provides a comprehensive guide for deploying the platform on various cloud providers, including AWS, GCP, and Azure. The guide focuses on using Rancher as the cluster management tool, making it applicable to a wide range of cloud providers supported by Rancher, as well as on-premises and hybrid cloud deployments.

> ***NOTE:*** The contents of this guide has been written and tested using Guardian 2.14.2 and Rancher 2.7, the latest stable version at writing time. The guide might not be applicable to different versions, specially major versions.

### Rancher Deployment

To begin the Rancher deployment process, the first step is setting up a Rancher server. We'll assume the Rancher server will be created in the same cloud provider as the Guardian instance, but it's important to note that this is not mandatory. Alternatively, you can use a Rancher container distribution and run it locally, enabling you to deploy the Guardian instance to any cloud provider. However, having the Rancher server running in the cloud will be beneficial for future cluster management and monitoring.

* Rancher deployment on AWS: [Follow this official guide to deploy Rancher 2.7 on AWS](https://ranchermanager.docs.rancher.com/v2.7/getting-started/quick-start-guides/deploy-rancher-manager/aws)
* Rancher deployment on GCP: [Follow this official guide to deploy Rancher 2.7 on GCP](https://ranchermanager.docs.rancher.com/v2.7/getting-started/quick-start-guides/deploy-rancher-manager/gcp)
* Rancher deployment on Azure: [Follow this official guide to deploy Rancher 2.7 on Azure](https://ranchermanager.docs.rancher.com/v2.7/getting-started/quick-start-guides/deploy-rancher-manager/azure)

Once you have your Rancher server up and running, you can access it through the web interface, and you should see something like this:

<figure><img src="/files/jQUv7RbD9gc910S5YOWF" alt="" width="563"><figcaption><p>Rancher login page</p></figcaption></figure>

You should be able to log in with the credentials you created during the installation process. Once you're logged in, you'll be able to manage your clusters and deploy new ones on any cloud provider. Additionally, you'll see a couple of default clusters created by Rancher, one of them is the local cluster, which is the one where Rancher is running, and the other one is the `sandbox` cluster, which is a cluster created by Rancher to test deployments and other features.

### K8s cluster deployment

After setting up your Rancher server successfully, the next step is to deploy a Kubernetes cluster on your preferred cloud provider. In this guide, we will utilize the managed Kubernetes solutions offered by cloud providers. However, you also have the option to deploy a cluster using VMs, a different distribution like k3s, or even use the Rancher-provided sandbox cluster if you do not intend to use it for production workloads. At the moment of writing this document, the recommended Kubernetes version for AWS and Azure is 1.25, and 1.26 for GCP.

* Cluster deployment on AWS EKS: [Follow this official guide to deploy an EKS cluster](https://ranchermanager.docs.rancher.com/v2.7/how-to-guides/new-user-guides/kubernetes-clusters-in-rancher-setup/set-up-clusters-from-hosted-kubernetes-providers/eks)
* Cluster deployment on GCP GKE: [Follow this official guide to deploy a GKE cluster](https://ranchermanager.docs.rancher.com/v2.7/how-to-guides/new-user-guides/kubernetes-clusters-in-rancher-setup/set-up-clusters-from-hosted-kubernetes-providers/gke)
* Cluster deployment on Azure AKS: [Follow this official guide to deploy an AKS cluster](https://ranchermanager.docs.rancher.com/v2.7/how-to-guides/new-user-guides/kubernetes-clusters-in-rancher-setup/set-up-clusters-from-hosted-kubernetes-providers/aks)

After the cluster is created, you'll be able to navigate to the cluster management section to see details for the cluster like nodes. In that section you can edit the cluster configuration, add nodes, etc.

You can also explore the cluster by clicking on the cluster name on the left side menu. In this view you can list and create all resources in the cluster, including namespaces, controller, access permissions, services, helm applications, monitoring, etc. From now on we'll focus on this "exploration view", which is the one you'll use to deploy the Guardian components.

#### How to deploy Kubernetes manifests on Rancher

An important part of the Rancher UI is the top header, specially the namespace dropdown. This dropdown allows you to select the namespace where you want to deploy the manifests. By default, Rancher will create a namespace named `default`, but you can create as many namespaces as you want. Get familiar with this dropdown and check it to see the selected namespace before panicking if you don't see the resources you expect to see under any section.

<figure><img src="/files/mddh6Gfub4bwcuLB3wJx" alt="" width="563"><figcaption><p>Rancher header bar</p></figcaption></figure>

To deploy the manifests, you can use the Rancher web interface, or you can use the `kubectl` command line tool. For this guide we're going to use the command line tool. The reason to use the command line tool is because it allows to deploy an entire folder with a single command, but you can use the web interface if you prefer. Simply click on the :outbox\_tray:\[import yaml] button on the right of header bar on rancher ui for each file.

To use kubectl tool, you need first to install the tool and download the kubeconfig credentials file by clicking on the :page\_facing\_up:\[downlaod kubeconfig] icon on rancher header. You can also navigate to a kubectl console directly from the Rancher UI by clicking on the :terminal:\[kubectl shell] icon on rancher header.

### Guardian deployment

Once you have your cluster up and running, you can start deploying the different Guardian components. Not all of them are mandatory, and some of them can be replaced by managed services outside of the cluster. There is a [dedicated section](#types-of-services) on this document with details about the different types of services and the deployment options for external services.

For this guide we've divided the different manifests into several folders, which name is prefixed by a number, this is to indicate the order in which they should be deployed. The reason for this is that some of the components depend on others, so we need to deploy them in the right order to avoid errors and to ease service discovery.

#### Nginx ingress controller

The first component we need to deploy is the Nginx ingress controller. This component is used to expose the different services to the outside world. You can find more details about this component in the official documentation, but for this guide we're going to use the default configuration.

Complete information about this topic can be found in [this link](https://kubernetes.github.io/ingress-nginx/deploy), but here is a summary for the installation steps for the cloud providers referred on this document.

**AWS**

```bash
kubectl --kubeconfig KUBECONFIG-FILE apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/aws/deploy.yaml
```

**GCP**

```bash
kubectl --kubeconfig KUBECONFIG-FILE apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml
```

**Azure**

```bash
kubectl --kubeconfig KUBECONFIG-FILE apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml
```

After this step is completed you should see a Load Balancer service created in your cluster with a external IP address where you'll have access to Guardian once it is deployed. You can check the status of the service by running the following command:

```bash
kubectl --kubeconfig KUBECONFIG-FILE -n ingress-nginx get svc -o wide

```

You can also find the load balancer using your cloud provider console. The domain name configuration and, DNS records and TLS certificates with SSL termination on the load balancer are out of the scope of this document.

#### Guardian manifests

Simply run the following commands to deploy the manifests. You can find more details about the different components below, in the manifests [folder structure section](#manifests-folder-structure).

To use a namespace different than default one, you need to add the `--namespace <namespace>` flag to the commands above. And create the namespace before running the commands.

```bash
kubectl --kubeconfig KUBECONFIG-FILE apply -f ./k8s-manifests/1-config/
kubectl --kubeconfig KUBECONFIG-FILE apply -f ./k8s-manifests/2-service/
kubectl --kubeconfig KUBECONFIG-FILE apply -f ./k8s-manifests/3-controller/
```

> ***PRO-TIP:*** if you plan to use the web ui, this command executed locally may help to deploy all manifests on a single shot by coping in your clipboard a huge text with all the manifests content together: `find k8s-manifests -type f | sort | xargs cat | pbcopy` for macos, or `find k8s-manifests -type f | sort | xargs cat | xsel -b` for linux users.

#### Manifests folder structure <a href="#manifests-folder-structure" id="manifests-folder-structure"></a>

**1-config**

This folder contains configuration manifests that are required for the rest of the components to work. You can find more details about the configuration in the relevant section fo the documentation, but for the demonstration of this document, the only important file is `0-general-config.yaml`, which contains the configuration for the different services. You can edit this file to change the configuration of the services. The rest of the files are related to the specific settings each individual service can override, based on the multi-environment feature.

**Multi-environment feature settings**

The key settings to turn on the multi-environment feature are GUARDIAN\_ENV and OVERRIDE. The first one is used to indicate the environment name, and the second one is used to indicate if the service should override the default configuration or not. If the service is not overriding the default configuration, it will use the default one. If the service is overriding the default configuration, it will use the configuration defined in the service manifest.

> ***NOTE:*** when using the multi-environment feature, each service will try to read its config file from a file named `.env.gateway.${GUARDIAN_ENV}`, that file is not mounted in the manifests, so you'll need to update the corresponding controller manifests and re-deploy them, and deploy before the new configSet. See below a simplified example:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo-service
spec:
  replicas: 2
  selector:
    matchLabels:
      service: foo-service
  template:
    spec:
      containers:
          image: gcr.io/hedera-registry/foo-service
          name: foo-service
          volumeMounts:
            - mountPath: /usr/local/foo-service/configs/.env.foo.${GUARDIAN_ENV}
              name: foo-service
              subPath: .env
      volumes:
        - configMap:
            items:
              - key: .env.foo.${GUARDIAN_ENV}
                path: .env
            name: foo-service
          name: foo-service
```

**2-service**

This folder contains the manifests for the different services that needs to be created in the cluster. Not all of them are exposed to the outside world, and some of them are only used internally by other services.

> ***NOTE:*** the manifest `web-proxy-ingress.yaml` creates the external routes for the exposed services. Some of them are potentially dangerous if exposed to the internet, for example, `/mongo-admin`, so please make sure you understand the implications of exposing them before doing so and disable the ones you don't need or protect them.

**3-controller**

This folder contains the manifests for the different controllers that needs to be created in the cluster. These controllers are used to manage the lifecycle of the different services, and to ensure they are always running and healthy. This is the folder you need to pay attention if you want to deploy service versions different than the provided one.

> ***NOTE:*** you may face compatibility issues if you try to deploy different Guardian versions with the provided manifests. Check version release notes before.

> ***NOTE:*** all the manifest modifications described in the whole document can be done also easily in the Rancher UI, navigating to the relevant section and editing the default deployed objects.

### Types of services <a href="#types-of-services" id="types-of-services"></a>

#### External (third-party services)

These are third party services that are not part of the Guardian platform, but are required for some of the Guardian components to work. You can choose to deploy them inside the cluster or use managed services outside of the cluster. For heavy workloads, the recommendation would be to use external dedicated services. The project included manifests described above cover their basic setup, but to see all the details about installation and configuration, please refer to the official documentation of each service.

* mongo
* ipfs/kubo
* message-broker
* HashiCorp vault
* mongo-express

For production workloads it is recommended to use a more robust setup for these services, like a replica set for mongo, a cluster for ipfs, a cluster for the message broker, etc. Navigating to the Apps section of Rancher, you can find the official [Helm](https://helm.sh/) charts for these services, with Rancher support, which can be used to deploy them in a more robust way. As an example, you can follow the steps below to deploy a message broker cluster using the Rancher UI, you'll see something similar to this:

<figure><img src="/files/IGgEMZgQ2z04cmmAKy0J" alt=""><figcaption><p>Rancher charts section</p></figcaption></figure>

1. Navigate to the Apps section of Rancher.
2. Click on the :heavy\_plus\_sign:\[Charts] button.
3. Select the `nats-server` chart (use the search bar if neeeded), read the chart documentation and click on the install button.
4. Follow the installation steps selecting the namespace where you want to deploy the chart, and filling the required values, like in this case, the number of replicas. You can also edit the raw `values.yaml` file, with all the customizable options the chart provides.
5. Once the chart is successfully deployed you can navigate to the services section, see the details of the service, copy the dns name and update the relevant config map containing the connection string for the message-broker service.
   * because the internal guardian services read the configuration from environmental variables, you'll need to redeploy them to apply the changes. To do that navigate to the Rancher workloads section, select the relevant deployments and click on the :arrows\_clockwise:\[Redeply] button.

This same steps can be followed to deploy the rest of the external services, like mongo, ipfs, etc. using Helm charts. One particularly interesting one is kube-prometheus-stack, which is a collection of charts that can be used to deploy a full monitoring stack for the cluster, including prometheus, prometheus-alerts and grafana. In this particular case, Rancher has rebranded the chart as `rancher-monitoring`, so you can follow the same steps described above to deploy it.

#### Internal (Guardian services)

These are the Guardian services that are part of the platform and are required for the platform to work. They are all deployed inside the cluster and are managed by Rancher. Depending on your needs, you may decide not to deploy some of them, like the frontend, so feel free to skip the ones that are not relevant for your use case. For all of them, the project includes a service, a deployment manifest and a configuration sample manifest using config maps. These manifests are used to create the service and the deployment for the service. The deployment manifest is used to create the pods that will run the service, and the service manifest is used to create the service that will expose the pods to the rest of the cluster.

* mrv-sender
* topic-viewer
* logger-service: requires message-broker
* auth-service: requires mongo, vault, logger-service
* policy-service: requires auth-service
* worker-service-1: requires ipfs-node, auth-service
* worker-service-2: requires ipfs-node, auth-service
* guardian-service: requires worker-service-1, worker-service-2, policy-service
* api-gateway: requires guardian-service
* application-events: requires guardian-service
* frontend

Please, explore the rest of the documentation to learn more about the different services, their configuration, upgrading guides and so on.


# Upgrading

## Introduction

This document can be used as a tool to implement an upgrade process in the Hedera Guardian application. It provides detailed step-by-step instructions for upgrading an open-source Hedera Guardian application from the current version to the target version. It includes expanded information and additional guidance for each section of the upgrade process. Please follow the instructions outlined below:

### Actors and Participants

The actors that will be involved in the guardian upgrading process are:

* Guardian Development Team
  * Solution development.
  * Documentation provisioning.
* Guardian Administrator (customer side)
  * Backup execution.
  * Scripting Execution.
  * Configuration customization.

## Theory

### Requirements

Depending on how large the upgrades are, there could be a lot of work keeping versions correct. Proper tools, documentation, and methodologies should be created to respond to upgrade needs (How will our customers upgrade their solution? What solutions need to be put in place? Etc.)

Related requirements:

1. Find a qualified source to create an enterprise-grade version of Guardian;
2. Consolidate, package, and normalize the solution architecture to match development best practices, supporting existing Hedera environments (currently defined as a local node, testnet, previewnet, or mainnet) deployed on-premises and on clouds;
3. Cloud Infrastructure: All Guardian source code and secrets should be deployed via Infrastructure as Code in cloud. In particular, the repo should contain all the artifacts and the documentation for the deployment of the Guardian on Amazon Web Services, Google Cloud Platform and Microsoft Azure.

### **Data Upgrading Process**

The upgrading of the Guardian functionalities may include the necessity of applying changes in the database schemas. In this case the Process of Upgrading is split between Developer and Customer.

Data Upgrading process involves the developer team providing the solution for Upgrading while the Customer is the solution executer. The main problem while upgrading a run time operational database is the migration of all data from the previous version schema to the new version.

The migration process guides the team to produce artifacts that will help to correctly define the migration itself and the customer to decide for upgrading and executing the data migration.

In this case the migration that we account for is an homogeneous migration: a migration from source databases to target databases where the source and target databases are of the same database management system. During upgrading the system, the schemas for the source and target databases are almost identical except for changes in some of the fields, collections and documents. For changing data the source databases must be transformed during migration.

#### 1) Data Migration Profiling:

Without a good understanding of the Data model the organization could run into a critical flaw that halts the system and brings Guardian to stop for data corruption and inconsistency. This phase would have “Data Migration Model” as output. This document outlines all the data that needs to be migrated, the complete mapping between the Data Source and Data Destination and every transformation in terms of:

* **Data type**: to cast the source value into the target value based on type transformation rules.
* **Data structure**: to describe modification of the structure of a collection in the database model.
* **Data value**: to change the format of data without changing the data type.
* **Data enrichment and correlation** (adding and merging to one collection).
* **Data reduction and filtering** (splitting to several collections).
* **Data views**: to allow the maintenance of DAO contracts during Data reduction.

Furthermore, the document should:

* Map every data to User Functionality (Rest API) that involves that data.
* Map every data to messages data flows to realize the functionality.
* Specify data replication in the guardian data sources (only DB Data, Blockchain Data, Multi Service).
* Break the data into subsets to determine all the data changes that have to be applied together.

The document has to specify the following data parameters:

* Expected size of your data,
* the number of data sources,
* the number of target systems,
* Migration time evaluation per data size reading, writing, network latency and the expected time per expected data size.

#### 2) **Design phase**: this phase has the “Design Document” as output.

The type of data migration could be either big bang or trickle:

* In a big bang data migration, the full transfer is completed within a limited window of time. Live systems experience downtime while data goes through ETL (Extract, transform, load) processing and transitions to the new database.
* Trickle migrations, in contrast, complete the migration process in phases. During implementation, the old system and the new are run in parallel, which eliminates downtime or operational interruptions. Processes running in real-time can keep data migrating continuously.

The document should contain:

* the requirements and the timeline for the project. Allocate time for every testing phase and validation phase.
* Should define the migration type as described above.
* Should consider [security plans](https://www.talend.com/resources/gdpr-pillar-3-anonymize-pseudonymize/) for the data. Any data that needs to be protected should have protection threaded throughout the plan.
* Establish data quality and health checks by determining which[ data integrity problems](https://www.talend.com/resources/reduce-data-integrity-risk/) could arise from your data set.
* The Migration process needs to be detailed, taking care of:
  * Target database addressing using environment description.
  * Persistence of in-transit data: To resume at the point where special events happen, the system needs to keep an internal state on the migration progress: Errors, Connection Lost, large window processing of the data, provides process repeatability.
  * Define how to track the items that are filtered out from transformation/migration phases , you can then compare the source and target databases along with the filtered items.
  * For every batch of data define the exact plan and roll back strategy
  * Define Customer test to verify consistency: This check ensures that each data item is migrated only once, and that the datasets in the source and target databases are identical and that the migration is complete.
* Define roles and responsibilities of the data migration.
* A Validation phase has to be defined with:
  * Who has the authority to determine whether the migration was successful?
  * After database migration, who will validate data?
  * Which tool will help in data validation: this tool will be the main instrument to verify data consistency. This check ensures that each data item is migrated only once, and that the datasets in the source and target databases are identical and that the migration is complete.
* Define backup and disaster recovery strategies. Create a DB backup of Mongo: replica set is a very good solution for availability but to provide real backup solution define a dedicated backup Mongo copy.

#### 3) Build the Migration Solution

Break the data into subsets and build out migration of one category at a time, followed by a test. (TOOL) The Developer

#### 4) Build the consistency validation Test

Build the customer check to compare the source and target databases along with the filtered items.

#### 5) Back up

The data before executing. In case something goes wrong during the implementation, you can’t afford to lose data. Make sure there are backup resources and that they’ve been tested before you proceed (MongoDB: Replica set).

#### 6) Conduct a Live Test

The testing process isn’t over after testing the code during the build phase. It’s important to test the data migration design with real data to ensure the accuracy of the implementation and completeness of the application: consistency test. (TOOL)

#### 7) Execute the plan

Implementing what described in step 2. (TOOL)

Migrate data in batches. Migration can take a long time, so batching up the data will prevent any interruption in service. Once the first batch is successfully migrated and tested, you can move on to the next set and revalidate accordingly.

#### 8) Test your migration process

During the first batch of data being migrated, try to analyze all the steps and see if the process is completed successfully or if it needs to be modified before moving on to the next batch.

#### 9) Validation Test

You need to verify that your database migration is complete and consistent. Before you deploy this production-level data, test the new data with real life scenarios before moving it to production in order to validate that all the work done aligns with the overall plan.

#### 10) Audit

Once the implementation has gone live, set up a system to audit the data in order to ensure the accuracy of the migration. (Performance and monitoring)

### Migration Consistency

The expectation is that a database migration is consistent. In the context of migration, consistent means the following:

* **Complete**. All data that is specified to be migrated is actually migrated. The specified data could be all data in a source database or a subset of the data.
* **Duplicate free**. Each piece of data is migrated once, and only once. No duplicate data is introduced into the target database.
* **Ordered.** The data changes in the source database are applied to the target database in the same order as the changes occurred in the source database. This aspect is essential to ensure data consistency.

An alternative way to describe migration consistency is that after a migration completes, **the data state between the source and the target databases is equivalent**. For example, in a homogenous migration that involves the direct mapping of a relational database, the same tables and rows must exist in the source and the target databases.

### Tools Comparison

#### Self scripted tools

These solutions are ideal for small-scale projects and quick fixes. These can also be used when a specific destination or source is unsupported by other tools. Self-Scripted Data Migration Tools can be developed pretty quickly but require extensive coding knowledge. Self-Scripting solutions offer support for almost any destination or source but are not scalable. They are suitable only for small projects. Most of the Cloud-Based and On-Premise tools handle numerous data destinations and sources.

* Scalability: Small and 1 Location
* Flexibility: any data
* Maintenance, error management, Issues during execution

Some reasons for building database migration functionality instead of using a database migration system include the following:

* You need full control over every detail.
* You want to reuse functionality.
* You want to reduce costs or simplify your technological footprint.

#### On-Premise tools

On-Premise solutions come in handy for static data requirements with no plans to scale. They are data center level solutions that offer low latency and complete control over the stack from the application to the physical layers.

* Data center migration level.
* Limited scalability.
* Secure: give full process control.

#### CloudBased tools

Cloud-Based Data Migration Tools are used when you need to scale up and down to meet the dynamic data requirements (mainly in ETL solution). These tools follow a pay-as-you-go pricing that eliminates unnecessary spending on unused resources.

* Based on the cloud.
* Big Scalability.
* Has security concerns.

#### Data Migration Software parameters

**Setup**: easy set up in your environment.

**Monitoring & Management:** provides features to monitor the ETL process effectively. Enable users to take reports on various crucial data sets.

**Ease of Use**: learning curve.

**Robust Data Transformation**: data transformation feature after the data is loaded into the database. You can just useSQL.

| <p><br></p>              | **Setup**                       | **Monitoring & Management** | **Ease of Use**                  | **Robust Data Transformation**      | **Pricing / Open Source**  |
| ------------------------ | ------------------------------- | --------------------------- | -------------------------------- | ----------------------------------- | -------------------------- |
| **Custom functionality** | Npm/Coding                      | no                          | Yes integrated in the solution   | Tested Npm tool: migrate-mongo      | free                       |
| **AWS Data Pipeline**    | yes                             | yes                         | yes                              | yes                                 | $0.60 to $2.5 per activity |
| **Hevo Data**            | yes                             | yes                         | yes (Autoschema mapping)         | yes                                 | FREE (1 million events)    |
| **Talend Open Studio**   | yes                             | no                          | By GUI                           | yes                                 | Open Source / Free         |
| **MongoSyphon**          | JSON format configuration files | No                          | no GUI, SQL, scheduling via cron | early stage tool, SQL               | Open Source / Free         |
| **Meltano**              | yes                             | Airflow                     | yes                              | yes                                 | Open Source / Free         |
| **Singer**               | Python                          | No                          | No                               | taps and targets (Meltano provided) | Open Source / Free         |
| **AirByte**              | yes                             | No                          | yes                              | SQL, dbt                            | Free                       |

Several other tools and pricing both on open source and commercial:

* <https://www.talend.com/resources/understanding-data-migration-strategies-best-practices/>
* <https://hevodata.com/learn/best-mongodb-etl-tools/>
* [https://hevodata.com/learn/data-migration-tools/](https://hevodata.com/learn/data-migration-tools/#AzureDocumentDB)
* <https://blog.panoply.io/top-9-mongodb-etl-tools>
* <https://airbyte.com/>
* <https://cloud.google.com/architecture/database-migration-concepts-principles-part-1>

### Services Upgradability Service Profiling and data migration mapping

To describe services we introduce “Services canvas”. A microservice canvas is a concise description of a service. It’s similar to a CRC (Class-responsibility-collaboration) card that’s sometimes used in object-oriented design. This is a template which allows a synthetic description of the service itself both for developers and stakeholder clarity. It will be compiled by developers and architects, and will be used as input during the delivery of the data migration process.

It has the following section: Service Name, Managed Data, Dependencies, Service API.

Canvas wil be used to describe the development realized in that very release in a way to be introduced incrementally. The Upgrade canvas is built not as a complete Service Canvas, but it must only describe the upgrading of the service/functionalities. In this way it will directly contain the same items really implemented in the release. A complete description of the service could also be provided in a SERVICE CANVAS that is out of the scope of the upgrading, much more difficult to be produced and more design oriented than the document.

| **Main Parameters** | <p><br></p>                                  |
| ------------------- | -------------------------------------------- |
| Name                | Name of Service                              |
| Description         | <p><br></p>                                  |
| Type of Development | < Creation, Update, Deletion >               |
| Version             | < Major, Minor, Patch >                      |
| Capabilities        | <ul><li>Main Service Functionality</li></ul> |

| **Managed Data**     |                                                                                                                 |
| -------------------- | --------------------------------------------------------------------------------------------------------------- |
| Collection Names:    | <p><br></p>                                                                                                     |
| Type of Development: | < Creation, Update, Deletion >                                                                                  |
| Data Model Reference | <p>If Creation: Document JSON Document Reference Link</p><p>If Update: Data Mapping Document Reference Link</p> |

| **Dependencies**                                                                                                                                                                             |                                                                                                                                                                                       |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Invokes                                                                                                                                                                                      | Invoked by                                                                                                                                                                            |
| <p>\<Service1Name>:</p><ul><li>Service1FunctionName()</li></ul><p>\<Service2Name>:<br></p><ul><li>Service2FunctionName()</li><li>….</li></ul><p><br></p>                                     | <p>\<Service2Name>:</p><p><br></p><ul><li>Service3FunctionName()</li></ul><p><br></p><p>\<Service3Name>:</p><p><br></p><ul><li>Service2FunctionName()</li><li>….</li></ul><p><br></p> |
| Subscribes to                                                                                                                                                                                | Subscribed by                                                                                                                                                                         |
| <p>\<Service3Name>:</p><ul><li>\<eventName1> event</li><li>\<eventName2> event</li></ul><p>Saga reply channels:</p><ul><li>\<SagaName1> Saga</li><li>\<SagaName2> Saga</li><li>…..</li></ul> | <p>\<Service3Name>:</p><ul><li>\<eventName1> event</li><li>\<eventName2> event</li></ul><p><br></p>                                                                                   |

| **Service API**                                                                                                                                                                                                                                                                                                     |                                  |                                                                                           |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------- |
| Commands                                                                                                                                                                                                                                                                                                            | Queries                          | Events                                                                                    |
| <p>Created:</p><p>Synchronous:</p><ul><li>FunctionName1()</li><li>FunctionName2()</li><li>…..</li></ul><p>Asynchronous:</p><ul><li>FunctionName3()</li><li>…..</li></ul><p><br></p><p>Updated:</p><p>Synchronous:</p><p>……</p><p>Asynchronous:</p><p>Deleted:</p><p>Synchronous:</p><p>Asynchronous:</p><p><br></p> | <ul><li>getFunctions()</li></ul> | <ul><li>Created</li><li>Authorized</li><li>Revised</li><li>Canceled</li><li>...</li></ul> |

\
[https://chrisrichardson.net/post/microservices/general/2019/02/27/microservice-canvas.html#:\~:text=A%20microservice%20canvas%20is%20concise,used%20in%20object%2Doriented%20design.](https://chrisrichardson.net/post/microservices/general/2019/02/27/microservice-canvas.html)

#### Service versioning and compatibility

To describe the compatibility between services in more detail it is possible to provide a square compatibility matrix.

To build this matrix it is possible to start with a dependency matrix detailing all the services dependent from one another in terms of service producers and service consumers. This matrix won’t be a complete correlation matrix but on the rows it will have just the upgraded and new services while on the columns it will show all services in the application.

| <p><br></p>   | **service1** | **service2** | **service3** | **service4** | **service5** | **service6** |
| ------------- | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |
| **Service 1** | <p><br></p>  | x            | x            | <p><br></p>  | <p><br></p>  | x            |
| **Service 3** | <p><br></p>  | <p><br></p>  | <p><br></p>  | x            | x            | <p><br></p>  |
| **Service 4** | <p><br></p>  | <p><br></p>  | x            | <p><br></p>  | <p><br></p>  | <p><br></p>  |
| **Service 6** | <p><br></p>  | x            | x            | x            | <p><br></p>  | <p><br></p>  |

Starting from this table it will be easier to infer the dependency between different versions of one service with the dependent ones versions.

For example

Service1 2.1.3 release is compatible with Service2 starting from version 1 until version 2.

Service1 2.1.3 is compatible with only with version 3.2.x of service3 and just bug fixes of that

Service 2.1.3 is backward compatible with with all versions of service6 until 4.x.x

Service 3.2.3 ……

| <p><br></p>                                                    | **service1** | **service2**             | **service3**            | **service4** | **service5** | **service6** |
| -------------------------------------------------------------- | ------------ | ------------------------ | ----------------------- | ------------ | ------------ | ------------ |
| **Service 1 2.1.3**                                            | <p><br></p>  | <p>1.x.x</p><p>2.x.x</p> | <p>3.2.x</p><p><br></p> | <p><br></p>  | <p><br></p>  | 4.x.x        |
| <p><strong>Service 3</strong></p><p><strong>3.2.3</strong></p> | …..          | ….                       | ….                      | <p><br></p>  | ..           | <p><br></p>  |
| **Service 4**                                                  | <p><br></p>  | <p><br></p>              | ..                      | <p><br></p>  | <p><br></p>  | <p><br></p>  |
| **Service 5**                                                  | <p><br></p>  | <p><br></p>              | ..                      | <p><br></p>  | <p><br></p>  | <p><br></p>  |
| **Service 6**                                                  | <p><br></p>  | ..                       | ..                      | ..           | <p><br></p>  | <p><br></p>  |

This solution is about to provide upgrading delta Online reference.

Here are two tools to implement the complete matrix analysis for microservices:

* <https://dzone.com/articles/dependency-structure-matrix-for-software-architect>
* <https://www.ndepend.com/docs/dependency-structure-matrix-dsm>

#### Data Model Reference

In case of newly introduced data, the data model section of the canvas will be the JSON document file that describes the collection itself.

In case of a data update, the reference Data Model will be the link to the Data mapping document.

The Data mapping document describes the model for the data migration. The document should outline all the data that needs to be migrated, the complete mapping between the Data Source and Data Destination and every transformation in terms of:

* **Data type:** to cast the source value into the target value based on type transformation rules.
* **Data structure:** to describe the structure modification of a collection in the database model.
* **Data value:** to change the format of data without changing the data type.
* **Data enrichment and correlation** (adding and merging to one collection).
* **Data reduction and filtering** (splitting to several collections).
* **Data views:** to allow the maintenance of DAO contracts during Data reduction.

The canvas Itself provides the framework in which the data belongs. Furthermore, the document should:

* Map every data to User Functionality (Rest API) that involves that data.
* Map every data to message data flows to realize the functionality.
* Specify data replication in the guardian data sources (only DB Data, Blockchain Data, Multi Service).
* Break the data into subsets to determine all the data changes that have to be applied together.

Here is how the mapping will look like

| Mapping Indicator | Change Description | Key Indicator | Source Collection | Source Field name | Source Field Length | Source Data Type | Business Rule                                            | Target Collection | Target Field Name | Target Data Type | Target Field Length | Description & comments |
| ----------------- | ------------------ | ------------- | ----------------- | ----------------- | ------------------- | ---------------- | -------------------------------------------------------- | ----------------- | ----------------- | ---------------- | ------------------- | ---------------------- |
| A                 | Split              | na            | Collection 1      | Field1            | 50                  | string           | Direct Mapping                                           | Collection2       | Field1            | string           | 50                  | <p><br></p>            |
| A                 | Split              | na            | Collection 1      | Field2            | 50                  | string           | Direct Mapping                                           | Collection3       | Field1            | string           | 50                  | <p><br></p>            |
| C                 | Split              | na            | Collection 1      | Field3            | 50                  | string           | <p>if "Sales" then "S"</p><p>if "Transport" then "T"</p> | Collection3       | Field2            | string           | 1                   | <p><br></p>            |

The following information is contained in the table:

1\) Mapping indicator (Values A: Add, D: Delete, C: Change)

2\) Change description (Indicates mapping changes introduced)

3\) Key Indicator (Indicates whether the field is a primary key or not)

4\) Source Table/Collection Name

5\) Source Field Name

6\) Source Field Length

7\) Source Field Data Type

8\) Source Field Description(The description will be used as a meta data for end user)

9\) Business Rule to transform data if needed

10\) Target Table/Collection Name

11\) Target Field Name

12\) Target Data Type

13\) Target Field Length

14\) Description and comments

### Methodologies, best practice for microservices upgrading

#### 1) Services should be organized around business domain boundaries:

Architects recommend the use of “separation of concerns”: strong internal cohesion in each microservice and loose coupling microservices should be grouped according to their problem domain.

Architects need to have a strong understanding of the relation between impacted use cases and backend data flows in a way to always map use case modification in backend microservices upgrading and know how data modification impacts inter-service messages between consumer and produced services and their APIs.

A service here has the sole authority over its data and exposes operations to other services.

#### 2) Keep admin scripts together with the application codebase

Guardian migration consists of a small script that runs as the first step of every first time installation performing a one-time load. Is it possible to write a small function to read and save data in batch into the database running these scripts offline.

Guardian already deals with this problem: Due to the long-term nature of some sustainability projects, Policy Engine (PE) maintains unlimited ‘read’ backward compatibility with 'old’ schema definition language elements. In other words, new PE versions will recognize and be able to process all existing valid policies with schemas defined starting from the beginning of Guardian existence. (<https://guardian.hedera.com/guardian/standard-registry/policies/versioning-and-deprecation-policy/policy-versioning-and-deprecation-policy>)

**Guardian dials with Schema breaking changes**

* Removing or renaming an element;
* Changing any of its non-descriptive properties e.g. type or readOnly status.

Deprecation Notice:

* Issued via the deprecated meta-data annotation;
* Release Notes;
* VC revocation notice is issued into the corresponding Hedera Topic.

<https://guardian.hedera.com/guardian/standard-registry/policies/versioning-and-deprecation-policy/policy-versioning-and-deprecation-policy>

**Guardian dials with Policy Breaking changes**

* Removing or renaming a block, changing any of its non-descriptive properties.
* Changing used schema version to a new one with breaking changes. **(Changes Impact)**
* Changing workflow sequence, dependencies or bind block.
* Introducing new, or changing existing external data sources.

<https://guardian.hedera.com/guardian/standard-registry/policies/versioning-and-deprecation-policy/api-versioning-and-deprecation-policy>

**Guardian dials with Breaking changes in general**

* Removing an API endpoint, HTTP method or enum value;
* Renaming an API endpoint, HTTP method or enum value;
* Changing the type of the field;
* Changing behavior of an API request.

#### 3) Every microservice should always explicitly declare all of its dependencies.

We should do this using a dependency declaration manifest. For NodeJS we have **NPM**.

A different possibility could be the use of dependency Management tools:

**ORTELIUS**: Ortelius is an open source, supply chain evidence catalog for publishing, versioning and sharing microservices and other Components such as DB objects and file objects. Ortelius centralizes everything you need to know about a component-driven architecture including component level ownership, SBOMs, vulnerabilities, dependency relationships, key values, deployment metadata, consuming applications and versions.

\
**ISTIO**: A completely different approach that has been found during the preparation of the present methodology. The approach suggests the usage of the Service Mesh pattern for microservices. Also this choice represents a viable path but needs rethinking to the platform architecture. Also the Documenting path proposed here will naturally facilitate the assumption of a similar pattern.

#### 4) A microservices app should be tracked in a single code repository and must not share that repository with any other apps.

Track it in a version control system. [Git](https://git-scm.com/) is the most popular version control system in use today and is almost ubiquitous.

**Versioning:**

All microservices should make it clear what version of a different microservice they require and what version they are.

A good way of versioning is through semantic versioning, that is, keeping versions as a set of numbers that make it clear when a breaking change happens (for instance, one number can mean that the API has been modified).

**Version Technique**

* URI versioning: In this approach, developers add version information directly to a service's [URI](https://www.techtarget.com/whatis/definition/URI-Uniform-Resource-Identifier), which provides a quick way to identify a specific version of the service by simply glancing at either the [URL or URN](https://www.cbtnuggets.com/blog/technology/networking/networking-basics-whats-the-difference-between-uri-url-and-urn). Here's an example of how that looks:
  * <http://productservice/v1.1.2/v1/GetAllProducts>
  * <http://productservice/v2.0.0/GetProducts>
* Header versioning: This microservice versioning approach passes version information through the HTTP protocol header “content-version” to specify a particular service.

#### 5) Microservice apps are supposed to dispose of a service and to handle it gracefully.

Application processes can be shut down on purpose or through an unexpected event. An application process should be completely disposable without any unwanted side-effects. Moreover, processes should start quickly.

An important part of managing dependencies has to do with what happens when a service is updated to fit new requirements or solve a design issue. **Other microservices may depend on the semantics of the old version or worse: depend on the way data is modeled in the database.**\
As microservices are developed in isolation, this means a team usually cannot wait for another team to make the necessary changes to a dependent service before going live. The way to solve this is through versioning. **All microservices should make it clear what version of a different microservice they require and what version they are.**

#### 6) Microservice apps are expected to run in an execution environment as stateless processes.

In other words, they can not store persistent state locally between requests.

## Upgrading Guardian

Guardian is a Microservices Application organized with an API Gateway and the Message System NATS. This architecture is natively thought of as a cloud application so it can be improved by deploying on cloud.

There are several benefits in deploying microservices architectures on cloud thanks to the Application Managers:

* The microservices are deployed independently and communicate by APIs. (We got it)
* The overall infrastructure gains resiliency to node failures. (Application Manager)
* The containerization can give the application bigger portability. (We got it)
* CI/CD strategies and automation are applicable to the microservices, making development cycles fast. (Could be implemented)
* It allows automatic resource allocation following the user demand and scaling the infrastructure horizontally.
* It allows the application to upgrade and maintain the availability of the overall system.

Our main target cloud infrastructures are: Azure, AWS, Google.

Although cloud targets infrastructures, **Azure** and **AWS**, namely, offer their own Containerized Application Manager infrastructure. Google developed the **Kubernetes** platform that became the standard de facto in the area. Overmore it is an open source platform so it is possible to use it on-premise as well. So Kubernetes became one of the most important Cloud Agnostic solutions. Both Azure and AWS provides their own container manager solution:

* Azure Container Apps (based on Kubernetes platform and technologies like [Dapr](https://dapr.io/), [KEDA](https://keda.sh/), and E[nvoy](https://www.envoyproxy.io/)),
* Azure App Services, optimized for web services **enables the deployment**:
  * From source code (gain cloud dependency);
  * From docker image;
  * From the docker-compose.yml file (the docker containers are inside a single AppService,single POD, rather than multiple AppServices as one might expect.) and
* Amazon elastic container registry.

At the same time, they offer services that grant direct access to Kubernetes: Azure has its **Azure Kubernetes Service (AKS)** while AWS has Amazon **EKS (and obviously on EC2)**.

When it comes to physical upgrades what we want is for customers to be able to upgrade Guardian in the cloud that they choose to go with for their enterprise solution. There will be the need to deploy new versions **without downtime** to maintain overall application stability. Every service will rely on others to be up and running, so you also need to maximize the availability of every service.

Three common deployment patterns are available for zero-downtime deployments:

• **Rolling deploy** — You progressively take old instances (version N) out of service while you bring up new instances (version N+1), ensuring that you maintain a minimum percentage of capacity during deployment.

• **Canaries** — You add a single new instance1 into service to test the reliability of version N+1 before continuing with a full rollout (A-B TESTING). This pattern provides an added measure of safety beyond a normal rolling deployment.

• **Blue-green deploys** — You create a parallel group of services (the green set), running the new version of the code; you progressively shift requests away from the old version (the blue set). This can work better than canaries in scenarios where service consumers are highly sensitive to error rates and can’t accept the risk of an unhealthy canary.

## Implementation : Upgrade Guide for Hedera Application

The methodology that we follow to upgrade the system is the Blue-Green deployment. This allows us to upgrade while minimizing the downtime and the risks involved in the upgrade itself. We create a new instance of Guardian running the new version, the green instance, and in this instance we run all the tests, after which, we switch all the traffic on this. The current environment, the blues one, runs at the same time and continues the normal operative.

The upgrade process requires that the team or the person running/executing the process should have minimum 3 to 5 years of experience in the following technologies to implement the upgrade process.

a. Backend development experience in NodeJS and npm packages.

b. MongoDB installation, using, and troubleshooting.

c. AWS or Azure experience of CLI and infrastructure.

d. Shell scripting, YAML, and Docker & Kubernetes.

The upgrade process should take between 40 and 80 hours, depending on the individual steps and any issues that arise during the process.

### Tasks Checklist prior to the upgrade

### Test on a copy of the production

In general, before initiating the upgrade process, it is highly recommended to create a copy of the production environment and perform testing on the replicated instance. By testing on a copy, you can identify and address any potential issues without impacting the live production environment.

* If any issues are encountered during the testing phase, take the appropriate steps to address them and resolve them before proceeding to the next steps.

For the Guardian Upgrade process the Green Instance will be the copy on which all the tests are going to be executed.

### Review the release notes and documentation

Thoroughly review the release notes and documentation provided for the target version. These resources will help you understand the changes, new features, and any potential breaking changes in the upgraded version.

You can find the installation guide and release notes for the target version in the Hedera Guardian [documentation](https://docs.hedera.com/guardian/guardian/readme/getting-started) and in the Guardian [official repository](https://github.com/hashgraph/guardian/releases).

### Perform a Database and Environment backup operation

It is essential to create a complete backup of the existing Hedera Guardian application and its associated databases before proceeding with the upgrade. This ensures that the application data is safeguarded and can be restored if needed.

Refer to this document, [Backup tool](https://docs.google.com/document/d/1PG7dKgKHigNBS-Bs5lHIdgwvObKzAWwkTLk1XY_9M0s/edit), for more details.

While backing up consider that until release 2.13.0 environment was described by **.env.docker**

files in every of the following folders: ./guardian, ./\<service-name>/ and for the following services: api-gateway, auth-service, guardian-service, logger-service, policy-service and worker-service.

But starting with release 2.13.0 environment is holded by two different kind of files depending on the kind of installation:

1. Complete Ecosystem: `.env.<GUARDIAN_ENV>.guardian.system`

At folder: ./guardian/configs

2. Single Service: `.env.<GUARDIAN_ENV>.<service-name>`

At folder: ./guardian/\<service-name>/configs/

Make sure to back up all these files. As for an example, starting from the implementation provided at [Backup tool](https://docs.google.com/document/d/1PG7dKgKHigNBS-Bs5lHIdgwvObKzAWwkTLk1XY_9M0s/edit):

1. configure /usr/local/bin to contain the whole guardian tree folders.
2. change line 6 of script configs-backup.sh from:

zip -r -D /tmp/configs.zip /usr/local/bin/configs

To

zip -i "\*env.\*" -r /tmp/configs.zip /usr/local/bin/guardian\\

This will ensure that the complete ecosystem environment is backed up.

### Perform Guardian Vault backup operation

Starting with release 2.12.1, Guardan can store secret data in dedicated KMS. It can be a self maintained Hashicorp vault server or third party KMS provided by a cloud infrastructure. This storage is mainly used to store user wallets for all the users as long as some important operational server side data (Operator: system wallet, IPFS api key, Access Token account).

KMS stored secret data also needs to be backed up too.

As an example, here is provided a script to backup Hashicorp Vault secrets. The execution of the script would provide the snapshot for the consul server that contains the Vault storage and copies the cryptographic material to access the vault after it is restored using the snapshot. The file could be added to Guardian Application to create the backup that is going to be stored in the file guardian/vault/hashicorp/backup/secret-backup.snap.

Create the file guardian/vault/hashicorp/scripts/consul/consul\_backup.sh with the following content.

### consul-backup.sh <mark style="color:green;">#!/bin/bash</mark>

```
BASE_DIR=$PWD/vault/hashicorp
BACKUP_DIR=$BASE_DIR/backup/
VAULT_ROOT_TOKEN_PATH=$BASE_DIR/vault/.root
CONSUL_ADDR=http://localhost:8500
```

<mark style="color:green;">**# Executes a vault read command using curl**</mark>

<mark style="color:green;">**# $1: URI vault path to be executed**</mark>

<mark style="color:green;">**# $2: name of the snapshot file**</mark>

```
read() {
 URL=$CONSUL_ADDR/$1
 OUTPUT=$BACKUP_DIR/$2
 curl $URL --output $OUTPUT
}
```

<mark style="color:green;">**# Execute the complete snapshot for the consul server**</mark>

`execute_backup() {`

<mark style="color:green;">**# create a backup dir /vault/hashicorp/backup**</mark>

`mkdir $BACKUP_DIR`

<mark style="color:green;">**# backup root access file**</mark>

`cp $VAULT_ROOT_TOKEN_PATH $BACKUP_DIR/.root`

<mark style="color:green;">**# copy TLS material**</mark>

`cp -r $CERT_REPOSITORY_DIR $BACKUP_DIR`

<mark style="color:green;">**# execute read from server and backup in secret-backup.snap**</mark>

```
 read v1/snapshot secret-backup.snap
}
echo "execute backup"
execute_backup
```

#### Ensure prerequisite accounts (Optional: Only for the first time installation)

Make sure you have a Hedera Testnet Account and a Web3.Storage Account readily available for the upgrade process. These accounts will be required during the upgrade process to facilitate compatibility and connectivity with the Hedera network.

\
Refer to the Hedera Guardian GitHub [repository](https://github.com/hashgraph/guardian) for more details.

#### Identify and document version-specific customizations

If the prior version of the Hedera Guardian application has been customized by your company to cater to specific requirements, thoroughly document all the customizations made. It is important to have a clear understanding of the changes to ensure a smooth transition to the upgraded version. Follow data upgrading process best practice for your custom data.

#### Identify performance behavior

Collect metrics from the current Guardian running instance to analyze performance, logs, and metrics to identify current instance behavior as of [monitoring tools](broken://pages/PmdGqWnSRBypn7K9qa2D) available for Guardian since release 2.12.1.

### Tasks Checklist during the upgrade

#### Clone the Guardian repository

Begin by cloning the Guardian repository using Git. Run the following command to clone the repository to your local environment:

git clone <https://github.com/hashgraph/guardian.git>

#### Follow the installation guide

Consult the installation guide provided in the Hedera Guardian documentation for the target version. This guide will provide detailed instructions on setting up and configuring the upgraded Guardian application in your environment.

Detailed installation steps can be found in the Guardian [installation guide](https://docs.hedera.com/guardian/guardian/readme/getting-started).

#### Update configuration files

Depending on the kind of installation that you are following: running as docker containers by an orchestrator(docker compose) or running manually after building executables, modify the relevant configuration files to include the necessary information for your account. This information is essential for establishing the connection with the Hedera network and IPFS while enabling seamless interaction with the blockchain.

Upgrading to a release later than 2.13.0, the configuration files differ from previous versions:

* for the execution by the orchestrator, first configure the .env file in the Guardian Application folder. Copy and paste the .env.template and configure the variables there, mainly the GUARDIAN\_ENV. Then configure the right file `.env.<GUARDIAN_ENV>.guardian.system` at folder ./guardian/configs, and finally copy and paste `.env.template.guardian.system` as with the examples provided in the folder itself.
* for the manual execution in the same node or in the free deployment style, you need to configure each of the services separately. Configure first the ./\<service-name>/.env file for each of the services and, secondly, configure `.env.<GUARDIAN_ENV>.<service-name>` at folder ./guardian/\<service-name>/configs/. Finally, copy and paste `.env.template.<service-name>` as with the examples provided in the folder itself.

#### Execute the upgrade process

Follow the specific instructions provided in the upgrade guide or release notes to perform the upgrade process for the Hedera Guardian application. Make sure to carefully follow each step to ensure a successful upgrade.

While performing the upgrade keep in mind that Guardian has the following four main data storage:

* The blockchain Hedera Net;
* The MongoDB Database;
* The KMS;
* The Configuration files.

This storage is the boundary conditions for Guardian application execution.

The methodology that we follow to upgrade the system is the Blue-Green Deployment, we create a new instance of guardian running the new version, the green instance, and in this instance we run the previously defined tests. To be sure that the behavior of the Guardian platform is not affected by the boundary conditions, we need to run it using the current starting state for all the storages.

Green Instance boundary condition:

* Use the same blockchain Hedera Net used by the blue instance already running: configure HEDERA\_NET appropriately;
* Clone the MongoDB Database;
* Use the same KMS;
* Configure the Environment as at [***Update configuration files***](#update-configuration-files)

If you are running Guardian as a docker container you can clone the mongo database using the following instruction:

1. Create a backup directory in the blue instance: Create a directory on your local system to store the backup files.
2. Use the docker run command with the `--volumes-from option` to access the mongo volume and perform the backup. Run the following command:

`docker run --rm --volumes-from guardian-mongo-1 -v /path/to/backup:/backup mongo bash -c "cd /data/db && tar cvf /backup/mongo-backup.tar ."`

This command creates a .tar archive of the mongo db data directory (/data/db) and saves it as mongo-backup.tar in the specified backup directory.

1. Copy the mongo-backup.tar in a folder /path/to/backup in the Green Instance.
2. In the Green Instance, modify the volumes section of the mongo service definition in docker-compose.yml file:

```
services:
 mongo:
   image: mongo:6.0.3
   command: "--setParameter allowDiskUseByDefault=true"
   restart: always
   volumes:
     - /path/to/backup:/data/db
   expose:
     - 27017
```

By specifying the backup directory as a volume, Docker Compose will mount the contents of the backup directory to the /data/db directory within the mongo container. This allows the container to access and use the previously backed up data.

If you are running Guardian manually, after building executables you can restore in the Green Instance mongo db, the backed up data obtained at [***Perform a Database and Environment backup operation***](#perform-a-database-and-environment-backup-operation)

About KMS, that is strongly recommended for your production environment, care to copy all the cryptographic material. This is held for every service based on the KMS configuration that you are using as specified at [Guardian Vault](https://docs.hedera.com/guardian/guardian/readme/guardian-vault) documentation. In particular, for Hashicorp vault, copy the .\<service>/tls folder in every Blue Instance of yours to the Green Instance homonymous services.

Now, the last element to worry about is the update of the Environment using the new configuration file obtained at [***Update configuration files***](#update-configuration-files)***.*** You can bootstrap the Green Instance of Guardian application and follow next steps.

#### Configure Load Balancer

Set up a load balancer to distribute traffic between the blue and green environments. Initially, configure the load balancer to direct all traffic to the blue environment.

### Tasks checklist after the upgrade

#### Test the upgraded application

After the upgrade, thoroughly test the functionality and performance of the Hedera Guardian application in the Green Instance. Conduct comprehensive testing of all major features and use cases to ensure they are functioning as expected in the upgraded version.

#### Security and integrity testing

Perform security and integrity testing on the upgraded application to identify any vulnerabilities or potential issues. Implement necessary security measures and address any identified vulnerabilities to ensure the application's robustness.

#### Validate customizations

If the implementer company had made any customizations to the prior version, reapply those customizations to the upgraded version. Verify that the customizations are working correctly and are compatible with the new version.

#### Update documentation and user guides

Review and update the application documentation, user guides, and any related internal resources to reflect the changes and new features introduced in the upgraded version. This will help users understand and leverage the enhancements brought by the upgrade.

### End of Blue-Green Upgrade

#### Switch Traffic to the Green Environment

Once testing is successfully completed:

1. Repeat the cloning steps to update the Green instance with the last transaction to avoid losing any data about transactions that may have happened during the testing phase.
2. Update the load balancer configuration to start directing the incoming traffic to the green environment.

#### Monitor and Rollback if Needed

Continuously monitor the green environment's performance, logs, and metrics to identify any issues or anomalies. Compare the result of previous metrics to the new revealed metrics as per the [monitoring tools](broken://pages/PmdGqWnSRBypn7K9qa2D) available for Guardian since release 2.12.1.

If any critical issues arise, you can quickly rollback by switching the load balancer to route all traffic back to the blue environment.

#### Complete Transition

Decommission the blue environment or keep it as a backup, depending on your requirements.


# Backup tools

To implement a backup and recovery strategy for installation data and transaction data in Hedera Guardian application here are the detailed guidelines/ steps to be followed:

## Guidelines

A. Determine what data needs to be backed up: Identify installation data and transaction data that needs to be backed up, determine the frequency at which it needs to be backed up.

B. Choose a backup storage location: Select a secure and reliable location to store your backups. Cloud storage services like Amazon S3, Google Cloud Storage, and Microsoft Azure are popular options.

C. Decide on a backup schedule: Define a backup schedule that ensures all critical data is backed up regularly and create a backup policy based on it.

D. Develop backup scripts: Write backup scripts in Node.js that automate the backup process. Use libraries like Node.js's built-in fs module or third-party libraries like node-schedule or node-cron to create and schedule backup jobs. Alternatively, we can use open source tools like "node-backup-manager" or "duplicity".

E. Test backups and recovery procedures: Test your backups regularly to ensure that the data is being backed up correctly and can be restored in the event of data loss. Develop recovery procedures that detail how to restore data from backups.

F. Monitor backups and automate notifications: Monitor the backup process to ensure that backups are being created and stored correctly. Automate notifications to alert you of any backup failures or issues.

G.Automate the backup process: Automating the backup process can save time and reduce the risk of human error.

H.Secure backups: Backups should be encrypted to prevent unauthorized access to sensitive data. This includes using strong passwords and encryption algorithms to protect data both in transit and at rest.

I.Test backups regularly: It is important to test backups regularly to ensure that the backup process is working correctly. This includes testing the restore process to ensure that data can be recovered in the event of a disaster.

J. Update backup strategy as necessary: Revisit your backup strategy periodically to ensure that it remains relevant and effective. Make changes as necessary based on changes to your data or infrastructure.

By following these steps, the implementer company can implement a backup and recovery strategy for the installation and transaction data in their Guardian application to protect them in the event of data loss or other issues.

## Guidelines in Detail

**A. Determine what data needs to be backed up: Identify installation data and transaction data that needs to be backed up, determine the frequency at which it needs to be backed up.**

### **Installation data:**

Installation data refers to the configuration settings and other data that are necessary to install and set up a software application. Some examples of installation data in a Guardian application might include:

1\. Server configurations: This includes information about the hardware and software requirements for the application to run, such as the operating system, CPU, memory, and storage.

2\. Environment variables: These are variables that specify settings for the environment in which the application runs. For example, they might include the database connection string, API keys, or other environment-specific settings.

3\. Application settings: These are settings that are specific to the application, such as the default language, time zone, or other user preferences.

4\. Dependencies: These binary files are the external libraries or modules that the application relies on to function correctly. They might include Node.js modules, third-party libraries, or other software packages. These executable files, required for the application to run, are part of the installation data.

5\. Scripts: These are scripts that are run during the installation process to perform certain tasks, such as setting up the **database schema** or initializing the application.

**Note**: The Guardian application does use a **MongoDB** database hence the database schema is part of the installation data that needs to be backed up.

6\. License agreements: These are the legal agreements that govern the use of the application and must be agreed upon before installation.

7\. Customizations: If you have made any customizations to your application or system during installation or setup, these customizations are part of the installation data and need to be backed up.

### Transaction data:

Transaction data in the Guardian application refers to the data related to user transactions or activities within the application. Examples of transaction data can include:

1. User registration and login information
2. User profile data such as name, email, and contact information
3. User-generated content such as posts, comments, and messages
4. Server logs and error logs that record server activities and errors
5. Session data that tracks user activity and preferences during a single session.
6. MongoDB data as entered by a standard registry user or by a field user.

In general, transaction data in the Guardian application includes any data that is generated or modified by different users’ actions within the application. This data is critical to the proper functioning of the application and must be backed up and protected in case of data loss or corruption.

**B. Choose a backup storage location: Select a secure and reliable location to store your backups. Cloud storage services like Amazon S3, Google Cloud Storage, and Microsoft Azure are popular options.**

When it comes to choosing a backup storage location, there are several factors to keep in mind to ensure that your data is secure and easily accessible. Here are some key considerations:

1. Security: Your backup storage location should be secure and protected against unauthorized access. This means using encryption and access controls to prevent data breaches.
2. Reliability: Your backup storage location should be reliable and have a high level of uptime. This means choosing a provider with a proven track record of reliability and ensuring that your data is backed up regularly.
3. Scalability: Your backup storage location should be scalable and able to accommodate your growing data needs. This means choosing a provider that can easily scale up or down as your business needs change.
4. Accessibility: Your backup storage location should be easily accessible, both in terms of physical location and connectivity. This means choosing a provider with multiple data centers in different geographic locations and ensuring that you have reliable internet connectivity.
5. Cost: Your backup storage location should be cost-effective, without sacrificing security or reliability. This means comparing prices from different providers and choosing one that offers the best balance of cost, security, and reliability.
6. Compliance: Your backup storage location should comply with any relevant data protection regulations, such as GDPR or HIPAA. This means choosing a provider that has the necessary certifications and can provide proof of compliance.

By keeping these factors in mind, you can choose a backup storage location that meets your business needs and ensures the security and accessibility of your data.

**C. Decide on a backup schedule: Define a backup schedule that ensures all critical data is backed up regularly and create a backup policy based on it.**\\

When deciding on a backup schedule, there are several important factors to consider to ensure that your data is protected and easily recoverable in the event of a disaster or data loss. Here are some key considerations:

1. Recovery Point Objective (RPO): The RPO is the maximum amount of data that can be lost before it starts to impact your business. When deciding on a backup schedule, you should consider your RPO and ensure that your backups are frequent enough to meet this requirement.
2. Recovery Time Objective (RTO): The RTO is the amount of time it takes to restore your data after a disaster or data loss. When deciding on a backup schedule, you should consider your RTO and ensure that your backups are frequent enough to meet this requirement.
3. Data Volume: The size of your data volume will affect the backup schedule. Large volumes of data will require more time to back up, so you may need to schedule backups more frequently.
4. Data Criticality: The criticality of your data will also affect the backup schedule. Critical data should be backed up more frequently than non-critical data to minimize the risk of data loss.
5. Backup Window: The backup window is the time during which backups can be performed without impacting the performance of your systems. When deciding on a backup schedule, you should consider your backup window and ensure that backups are scheduled during a time when they will not impact system performance.
6. Backup Type: The type of backup you use will also affect the backup schedule. Full backups may take longer to perform, but they provide complete data protection. Incremental and differential backups may be faster, but they provide less complete data protection.

By considering these factors, you can develop a backup schedule that meets your business needs and ensures the protection and recoverability of your data.

**D. Develop backup scripts: Write backup scripts in Node.js that automate the backup process. Use libraries like Node.js's built-in fs module or third-party libraries like node-schedule or node-cron to create and schedule backup jobs. Alternatively, we can use open source tools like "node-backup-manager" or "duplicity".**

Example 1: Example backup script in Node.js that uses the built-in fs module to automate the backup process.

```
const fs = require('fs');
const { exec } = require('child_process');
const backupDir = '/path/to/backup/directory'; // The directory where backups will be stored
const sourceDir = '/path/to/source/directory'; // The directory to be backed up
const fileName = `backup_${new Date().toISOString()}.tar.gz`; // The filename for the backup file
// Create a backup of the source directory
const createBackup = () => {
  return new Promise((resolve, reject) => {
    exec(`tar -czf ${backupDir}/${fileName} ${sourceDir}`, (err, stdout, stderr) => {
      if (err) {
        console.error(`Error creating backup: ${err.message}`);
        reject(err);
      }
      console.log(`Backup created successfully: ${fileName}`);
      resolve(fileName);
    });
  });
};
// Copy the backup file to a remote server
const copyBackup = (backupFile) => {
  return new Promise((resolve, reject) => {
    const remoteHost = 'user@remote.host'; // The remote server to copy the backup to
    exec(`scp ${backupDir}/${backupFile} ${remoteHost}:${backupDir}`, (err, stdout, stderr) => {
      if (err) {
        console.error(`Error copying backup to remote server: ${err.message}`);
        reject(err);
      }
      console.log(`Backup copied to remote server successfully: ${backupFile}`);
      resolve();
    });
  });
};
// Delete old backup files to free up space
const deleteOldBackups = () => {
  const backupRetentionPeriod = 30; // The number of days to keep backup files
  const currentTime = Date.now();
  fs.readdirSync(backupDir).forEach((file) => {
    const filePath = `${backupDir}/${file}`;
    const fileStat = fs.statSync(filePath);
    const fileAge = (currentTime - fileStat.mtimeMs) / (1000 * 60 * 60 * 24); // Convert age to days
    if (fileAge > backupRetentionPeriod) {
      fs.unlinkSync(filePath);
      console.log(`Deleted old backup file: ${file}`);
    }
  });
};
// Run the backup process
const runBackup = async () => {
  try {
    const backupFile = await createBackup();
    await copyBackup(backupFile);
    deleteOldBackups();
  } catch (err) {
    console.error(`Error running backup process: ${err.message}`);
  }
};
runBackup();
```

Example 2:.Example backup script in Node.js that uses the "node-schedule" library to automate the backup process.

```
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const schedule = require('node-schedule');
// Define backup directory path
const backupDir = path.join(__dirname, 'backups');
// Ensure that backup directory exists
if (!fs.existsSync(backupDir)) {
  fs.mkdirSync(backupDir);
}

// Define source directory to backup
const sourceDir = path.join(__dirname, 'myApp');

// Define backup function
const backup = () => {
  // Define backup file name and path
  const backupFileName = `backup_${Date.now()}.tar.gz`;
  const backupFilePath = path.join(backupDir, backupFileName);
  // Execute backup command using child_process module
  const backupCommand = `tar -czvf ${backupFilePath} ${sourceDir}`;
  exec(backupCommand, (error, stdout, stderr) => {
    if (error) {
      console.error(`Backup error: ${error.message}`);
      return;
    }
    if (stderr) {
      console.error(`Backup stderr: ${stderr}`);
      return;
    }
    console.log(`Backup complete. Output: ${stdout}`);
  });
};
// Schedule backup to run every day at midnight
const backupSchedule = schedule.scheduleJob('0 0 * * *', backup);
// Log backup schedule information
console.log(`Backup scheduled to run every day at midnight: ${backupSchedule.nextInvocation()}`);

```

This script uses the "node-schedule" library to schedule a backup function to run every day at midnight. The backup function creates a backup file name and path, and executes a backup command using the child\_process module to compress and archive the source directory into a backup file in the backup directory. The script also includes error handling and logging capabilities to ensure that the backup process is reliable and can be monitored for issues.

Example 3: Backup script in Node.js that uses the "node-crone" library to automate the backup process.

```
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const cron = require('node-cron');
// Define backup directory path
const backupDir = path.join(__dirname, 'backups');
// Ensure that backup directory exists
if (!fs.existsSync(backupDir)) {
  fs.mkdirSync(backupDir);
}
// Define source directory to backup
const sourceDir = path.join(__dirname, 'myApp');
// Define backup function
const backup = () => {
  // Define backup file name and path
  const backupFileName = `backup_${Date.now()}.tar.gz`;
  const backupFilePath = path.join(backupDir, backupFileName);
  // Execute backup command using child_process module
  const backupCommand = `tar -czvf ${backupFilePath} ${sourceDir}`;
  exec(backupCommand, (error, stdout, stderr) => {
    if (error) {
      console.error(`Backup error: ${error.message}`);
      return;
    }
    if (stderr) {
      console.error(`Backup stderr: ${stderr}`);
      return;
    }
    console.log(`Backup complete. Output: ${stdout}`);
  });
};
// Schedule backup to run every day at midnight
cron.schedule('0 0 * * *', backup, {
  scheduled: true,
  timezone: 'America/New_York'
});
// Log backup schedule information
console.log('Backup scheduled to run every day at midnight in America/New_York timezone.');

```

This script uses the "node-cron" library to schedule a backup function to run every day at midnight in the America/New\_York timezone. The backup function creates a backup file name and path, and executes a backup command using the child\_process module to compress and archive the source directory into a backup file in the backup directory. The script also includes error handling and logging capabilities to ensure that the backup process is reliable and can be monitored for issues.

Example 4:.Example backup script in Node.js that uses the "node-backup-manager" library to automate the backup process.

```
const BackupManager = require('node-backup-manager');
// Initialize backup manager
const backupManager = new BackupManager();
// Configure backup options
const options = {
  backupDir: '/path/to/backup/directory',
  targets: [
    {
      name: 'mongodb',
      type: 'mongodb',
      host: 'localhost',
      port: 27017,
      database: 'mydatabase',
      username: 'myuser',
      password: 'mypassword',
    },
    {
      name: 'files',
      type: 'file',
      sourceDir: '/path/to/source/directory',
    },
  ],
};
// Schedule backups
backupManager.schedule(options, {
  interval: 'daily',
  at: '02:00',
});
// Start backup manager
backupManager.start();

```

In this example, we first import the node-backup-manager library and create an instance of the BackupManager class. We then configure the backup options by specifying the backup directory and the targets to be backed up. In this case, we have two targets: a MongoDB database and a file system directory.

Next, we schedule backups to be performed daily at 2:00 am using the schedule method. Finally, we start the backup manager using the start method.

Note that this is just a basic example, and you can customize the backup options and schedule according to your specific backup requirements.

Example 5:.Example backup script in Node.js that uses the "duplicity" library to automate the backup process.

```
const { spawn } = require('child_process');
// Set backup directory
const backupDir = '/path/to/backup/directory';
// Set source directories to be backed up
const sourceDirs = ['/path/to/source/directory', '/path/to/another/source/directory'];
// Set target URL for backup storage
const targetUrl = 's3://my-bucket/my-backup-folder';
// Set passphrase for encryption (optional)
const passphrase = 'my-passphrase';
// Set duplicity command options
const duplicityOptions = [
  '--no-print-statistics',
  '--s3-use-new-style',
  '--s3-use-ia',
  '--s3-use-multiprocessing',
  '--encrypt-key=MY_ENCRYPTION_KEY',
];
// Create backup command
const backupCommand = [
  'duplicity',
  '--full-if-older-than', '1M',
  ...duplicityOptions,
  ...sourceDirs,
  targetUrl,
];
// If passphrase is provided, add encryption option to command
if (passphrase) {
  backupCommand.splice(1, 0, '--encrypt-key');
  backupCommand.splice(2, 0, passphrase);
}
// Run backup command
const backupProcess = spawn(backupCommand[0], backupCommand.slice(1), {
  cwd: backupDir,
});
// Listen for backup process events
backupProcess.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});
backupProcess.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});
backupProcess.on('close', (code) => {
  console.log(`Backup process exited with code ${code}`);
});

```

In this example, we first set the backup directory, source directories to be backed up, target URL for backup storage, and passphrase for encryption (optional).

We then set the duplicity command options, including disabling statistics output, using S3 in new-style mode, using S3 Intelligent-Tiering, and using multiprocessing. We also specify the encryption key if a passphrase is provided.

Next, we create the duplicity backup command by combining the duplicity executable, the --full-if-older-than option to perform full backups after 1 month, the duplicityOptions, the sourceDirs, and the targetUrl. If a passphrase is provided, we add the encryption option to the command.

Finally, we use the child\_process.spawn method to run the duplicity command as a child process. We listen for events from the backup process, including stdout, stderr, and close events.

**E. Test backups and recovery procedures: Test your backups regularly to ensure that the data is being backed up correctly and can be restored in the event of data loss. Develop recovery procedures that detail how to restore data from backups.**

**F. Monitor backups and automate notifications: Monitor the backup process to ensure that backups are being created and stored correctly. Automate notifications to alert you of any backup failures or issues.**

**G. Update backup strategy as necessary: Revisit your backup strategy periodically to ensure that it remains relevant and effective. Make changes as necessary based on changes to your data or infrastructure.**

## Implementation: MongoDB and .env Files Backup

Backups are an important part of application development. In order to ensure this feature in the Guardian application the following steps could be taken if you want to save the backups in the Amazon S3. This [repository](https://github.com/IntellectEU/nodejs-app-backup) contains an example of how to simulate in detail the process to backup the mongodb collections and .env files. The same could be applied to the Guardian application.

1. Create a new folder called backup in the root folder of the Guardian Application.
2. Change the current docker-compose.yml in this service:

```
backup:
 build: ./backup
 environment:
   - AWS_ACCESS_KEY_ID=AKIAXC*******D6QV7
   - AWS_SECRET_ACCESS_KEY=Ipk6*****************sfMV
   - S3_BUCKET=application-backups
   - AWS_DEFAULT_REGION=eu-central-1
   - S3_MONGODB_PREFIX=mongodb
   - S3_CONFIGS_PREFIX=configs
   - BACKUP_NAME_FORMAT=mongodb-%Y-%m-%d-%H-%M-%S.archive
 volumes:
   - ./backup:/data
   - /var/run/docker.sock:/var/run/docker.sock
 depends_on:
   - mongodb

```

3. Create this folder structure:

<figure><img src="https://lh5.googleusercontent.com/jrskzKjjcdljK_uHD1TKFOhNXZlEaSSObnWF_PgbzytBH6V_yWN9e3kldiomolxGHB8gkSyiHAEB3WW2J6akuqQlby8YT52w_kAnRbqhDfjb3JKP9Z0oFRixC_yql5ULZor7t81bfmZ4e-d4ItPtb14" alt="" width="563"><figcaption></figcaption></figure>

4. The dockerfile will look like this:\
   \
   `FROM mongo:latest`\\

   \# Set the working directory

   `WORKDIR /usr/local/bin`

   `COPY . .`

   \# Install required tools

   `RUN apt-get update && apt-get install -y \`

   `curl unzip cron zip`\\

   \# Install AWS CLI dependencies

```
RUN apt-get update && apt-get install -y \
   python3 \
   python3-pip \
   groff \
   less \
   --no-install-recommends// Some code
```

\# Install AWS CLI

`RUN pip3 install awscli`

\
\# Add AWS CLI to the system path

`ENV PATH="/usr/local/aws-cli/bin:${PATH}"`

\# Copy your backup script to the container

```
COPY mongodb-backup.sh /usr/local/bin/mongodb-backup.sh
COPY configs-backup.sh /usr/local/bin/configs-backup.sh
```

\# Set execute permissions for the backup script

```
RUN chmod +x /usr/local/bin/mongodb-backup.sh
RUN chmod +x /usr/local/bin/configs-backup.sh
```

\# Copy the entrypoint script to the container

`COPY entrypoint.sh /usr/local/bin/entrypoint.sh`

\# Set execute permissions for the entrypoint script

```
RUN chmod +x /usr/local/bin/entrypoint.sh
CMD ["/usr/local/bin/entrypoint.sh"]
```

5. **Mongodb-backup.sh script:**

`#!/bin/bash`

\# Add a log entry indicating cron execution

`echo "$(date): Cron job executed" >> /var/log/mongodb-backup.log`

\# Dump the MongoDB data

`mongodump --uri="mongodb://host.docker.internal:27017" --gzip --archive=/tmp/mongo.gz`

\# Upload the backup to S3 using AWS CLI Docker image

`aws s3 cp /tmp/mongo.gz s3://$S3_BUCKET/$S3_MONGODB_PREFIX/$(date +%Y%m%d-%H%M%S).gz`

6. **Configs-backup.sh script:**

`#!/bin/bash`

\# Add a log entry indicating cron execution

`echo "$(date): Cron job executed" >> /var/log/configs-backup.log`

`zip -r -D /tmp/configs.zip /usr/local/bin/configs`

\# Upload the backup to S3 using AWS CLI Docker image

`aws s3 cp /tmp/configs.zip s3://$S3_BUCKET/$S3_CONFIGS_PREFIX/$(date +%Y%m%d-%H%M%S).zip`

7. **entrypoint.sh script:**

The script below will execute hourly to backup the database and the configuration files.

`#!/bin/bash`

\# Start cron

`service cron start`

\# Run the backup script in an infinite loop

```
while true; do
 /usr/local/bin/configs-backup.sh
 /usr/local/bin/mongodb-backup.sh
 sleep 1h  # Adjust the sleep duration as needed
done
```

*Remember that inside the config files we have .env files which are invisible unless you run `ls -lha command`.*

<figure><img src="https://lh5.googleusercontent.com/ZI-HVqLo8hXhgDvq---NvtIWGpXywR27Au-c-C5QAJeLGSSySGc3pplVwOCDZpxGu09IlPVy2VPayvm2EZ2wyAORpl8Bj0NL1dU8e19lNwv9ze7ZF_YRsi-KIrdQMYQWhYHLIkIBuPzTTmEkhHuzuHs" alt=""><figcaption></figcaption></figure>

<figure><img src="https://lh3.googleusercontent.com/h4j0tvoV7GWWeH5su1-I33-tlqN5xw_wLpb0aRAT__Mjf4sXRlz7gyyako96chOA-tOXEuvotCcLWcBwADDedtbN2XIVAgZbvHq8PMzRFf8AaMvHoOS1zX-wBfMIAXdIIaPo4LqHWY-qy47LcygsIoc" alt=""><figcaption></figcaption></figure>

The final result will look like the image above. After that you can easily download the last file of the configuration or of the database to be reintroduced in the application.


# Setting up environment parameters

### `.env / .env.docker` Parameters in `guardian-service`

<table><thead><tr><th width="379.1653645833333">Parameter</th><th width="271.2734375">Purpose</th><th>Example</th></tr></thead><tbody><tr><td>MQ_ADDRESS</td><td>Web Socket Address</td><td>localhost</td></tr><tr><td>SERVICE_CHANNEL</td><td>Version of the Guardian</td><td>guardian.1</td></tr><tr><td>DB_HOST</td><td>Hostname of the Database</td><td>localhost</td></tr><tr><td>DB_DATABASE</td><td>Database Name</td><td>guardian_db</td></tr><tr><td>INITIAL_BALANCE</td><td>Initial Balance Value</td><td>500</td></tr><tr><td>INITIAL_<em>STANDARD_REGISTRY_BALANCE</em></td><td>Setting Initial Standard Registry Balance</td><td>500</td></tr><tr><td>OPERATOR_ID</td><td>The ID of the operation</td><td>-</td></tr><tr><td>OPERATOR_KEY</td><td>Private key of the operator</td><td>-</td></tr><tr><td>LOCALNODE_ADDRESS</td><td>The address of the localnode server. This can be its IP address or a domain name</td><td>1.1.1.1</td></tr><tr><td>LOCALNODE_PROTOCOL</td><td>Communication protocol for interactions with the local node, can be http or https.</td><td>http/https</td></tr><tr><td>HEDERA_NET</td><td>Type of the Hedera node to transact with</td><td>testnet, localnode, mainnet</td></tr><tr><td>INITIALIZATION_<em>TOPIC_ID</em></td><td>The ID of the initialization topic.</td><td>0.0.1960</td></tr><tr><td>MESSAGE_LANG</td><td>Language of the message text of all messages</td><td>en-US</td></tr><tr><td>LOG_LEVEL</td><td>Level of the Logs</td><td>2</td></tr><tr><td>SEND_KEYS_TO_VAULT</td><td>Checked if keys to be sent to vault</td><td>True/False</td></tr><tr><td>MULTI_POLICY_SCHEDULER</td><td>to set custom cron mask (timer mask) for sync job</td><td>0 0 * * *</td></tr><tr><td>MQ_MESSAGE_CHUNK</td><td>To set up the message chunk size</td><td>500000</td></tr><tr><td>OVERRIDE_HEDERA_CONSENSUS_NODES</td><td>Define hedera nodes to execute and pay transaction fee</td><td>0.testnet.hedera.com:50211":"0.0.3</td></tr><tr><td>OVERRIDE_HEDERA_MIRROR_NODES</td><td>Define hedera mirror nodes</td><td>testnet.mirrornode.hedera.com:443"</td></tr><tr><td>MAP_API_KEY</td><td>Defines api to integrate Map schema type</td><td>ALZ_X.....</td></tr><tr><td>DOCUMENT_CACHE_FIELD_LIMIT</td><td>Defines document field symbols limit for caching.</td><td>500</td></tr><tr><td>BATCH_NFT_MINT_SIZE</td><td>Defines size of batch of mint NFT transaction</td><td>10</td></tr><tr><td>DIRECT_MESSAGE_PORT</td><td>Port for direct messages (if not set generate random port)</td><td>300</td></tr><tr><td>DIRECT_MESSAGE_HOST</td><td>Host for direct messages (if not set get hostname)</td><td>localhost</td></tr><tr><td>DIRECT_MESSAGE_PROTOCOL</td><td>Protocol https or http (http by default, https need additional server like nginx)</td><td>http</td></tr><tr><td>MQ_MAX_PAYLOAD</td><td>Max message size for send via message-broker (otherwise create direct message) if not set always send messages using message broker</td><td>35</td></tr><tr><td>RETIRE_CONTRACT_FILE_ID</td><td>Contract file ID for Retirement</td><td>0.0.4860665</td></tr><tr><td>WIPE_CONTRACT_FILE_ID</td><td>Contract file ID for wiping</td><td>0.0.4726865</td></tr><tr><td>DOCUMENTS_HANDLING_CHUNK_SIZE</td><td>To set chunk size for delete or create a lot of data (value will affect speed performance communication with DB), default is 500.</td><td>500</td></tr><tr><td>ALLOWED_PROTOCOLS="https"</td><td>This variable defines the list of allowed protocols that can be used in outbound HTTP requests made by the httpRequestBlock.</td><td>https</td></tr><tr><td>BLOCK_PRIVATE_IP</td><td>This variable controls whether the httpRequestBlock should reject outbound requests to private or sensitive IP address ranges.</td><td>True/False</td></tr><tr><td>OVERRIDE_HEDERA_MIRROR_NODES_BASE_API</td><td>This is automatically appended to every URL listed in <code>OVERRIDE_HEDERA_MIRROR_NODES</code></td><td>/api/v1</td></tr><tr><td>OVERRIDE_NETWORK_CONFIGURATION</td><td>Controls whether the <code>OVERRIDE_*</code> variables are applied at all.</td><td>True: apply override variables<br>False: ignore override variables and use default configuration</td></tr><tr><td>MIGRATION_HEARDBEAT_RUN_STALE_TIMEOUT</td><td>Defines how long a run can stay running without heartbeat updates before it is treated as stale</td><td>10</td></tr><tr><td>MIGRATION_WRITE_BATCH_SIZE</td><td>Database write batch size — number of items processed per batch.</td><td>50</td></tr></tbody></table>

{% hint style="info" %}
**Important Note:**

1. Values from .env file need to be set up only on first start (when db or vault are empty). Then later if you want it to be changed, you can change it through Settings from admin Panel or through API.
2. Now we have upgraded DB\_HOST (in guardian and indexer), DB\_LOGGER\_HOST (in guardian) settings and now it allows to set up Mongo Atlas connection string like mongodb+srv://.... which means that if you are explicitly setting up protocol it will be automatically applied OR if your using only host and port, it will automatically add mongodb:// (backward compatibility)
3. ALLOWED\_PROTOCOLS:

By default, only the https protocol is allowed:\
ALLOWED\_PROTOCOLS="https"

To allow multiple protocols, add them as a comma-separated list. For example:\
ALLOWED\_PROTOCOLS="https,http"

If a user attempts to use a protocol that is not explicitly listed, the request will be blocked during policy validation.

4. BLOCK\_PRIVATE\_IP:

By default, this value is set to "false", under the assumption that Guardian is not operating in an environment where internal services are exposed over https and accessible via external requests.

BLOCK\_PRIVATE\_IP="false"

To enforce strict protection and block all requests to private or loopback IP addresses, set the variable to:

BLOCK\_PRIVATE\_IP="true"
{% endhint %}

### `.env / .env.docker` Parameters in `api-gateway`

| Parameter                 | Purpose                                                                                                                             | Example                     |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
| MQ\_ADDRESS               | Web Socket Address                                                                                                                  | message-broker              |
| SERVICE\_CHANNEL          | Channel of the service                                                                                                              | api-gateway                 |
| MRV\_ADDRESS              | MRV Address location                                                                                                                | <http://message-broker/mrv> |
| MQ\_MESSAGE\_CHUNK        | To set up the message chunk size                                                                                                    | 500000                      |
| RAW\_REQUEST\_LIMIT       | Define request limit                                                                                                                | 1 gb                        |
| JSON\_REQUEST\_LIMIT      | Define limit for body in Json format                                                                                                | 1 gb                        |
| DIRECT\_MESSAGE\_PORT     | Port for direct messages (if not set generate random port)                                                                          | 300                         |
| DIRECT\_MESSAGE\_HOST     | Host for direct messages (if not set get hostname)                                                                                  | localhost                   |
| DIRECT\_MESSAGE\_PROTOCOL | Protocol https or http (http by default, https need additional server like nginx)                                                   | http                        |
| MQ\_MAX\_PAYLOAD          | Max message size for send via message-broker (otherwise create direct message) if not set always send messages using message broker | 35                          |

### `.env / .env.docker` Parameters in `auth-service`

| Parameter             | Purpose                                                                                                                                                                                                                                                                                                            | Example    |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| SR\_INITIAL\_PASSWORD | Allows to set SR initial password when it will be created first time. It also should have more than 5                                                                                                                                                                                                              | Env!s!0n!@ |
| MIN\_PASSWORD\_LENGTH | Sets the minimum password length. Default value is 8, minimum value is 1                                                                                                                                                                                                                                           | 8          |
| PASSWORD\_COMPLEXITY  | <p>Sets the password complexity level<br>Default value is medium<br>Available values: easy, medium, hard</p><ul><li>easy - no rules</li><li>medium - one uppercase letter, one lowercase letter, one number</li><li>hard - one uppercase letter, one lowercase letter, one number, one special character</li></ul> | medium     |


# Summary of URLs and Ports

### Using Docker:

<table><thead><tr><th width="199.33333333333326">Folder</th><th>URL</th><th>Target Deployment</th></tr></thead><tbody><tr><td>WEB_INTERFACE</td><td><a href="http://localhost:3000">http://localhost:3000</a></td><td>Production</td></tr><tr><td>API_GATEWAY</td><td><a href="http://localhost:3000/api/v1/">http://localhost:3000/api/v1/</a></td><td>Production</td></tr><tr><td>MRV_SENDER</td><td><a href="http://localhost:3000/mrv-sender/">http://localhost:3000/mrv-sender/</a></td><td>Demo</td></tr><tr><td>TOPIC_VIEWER</td><td><a href="http://localhost:3000/topic-viewer/">http://localhost:3000/topic-viewer/</a></td><td>Demo</td></tr><tr><td>API_DOCS</td><td><a href="http://localhost:3000/api-docs/v1/">http://localhost:3000/api-docs/v1/</a></td><td>Demo</td></tr><tr><td>MONGO-ADMIN-PANEL</td><td><a href="http://localhost:3000/mongo-admin">http://localhost:3000/mongo-admin</a></td><td>Demo</td></tr></tbody></table>

#### Not in Docker:

<table><thead><tr><th width="230.33333333333331">Folder</th><th>URL</th><th>Target Deployment</th></tr></thead><tbody><tr><td>WEB_INTERFACE</td><td><a href="http://localhost:4200/">http://localhost:4200/</a></td><td>Production</td></tr><tr><td>API_GATEWAY</td><td><a href="http://localhost:3002/">http://localhost:3002/</a></td><td>Production</td></tr><tr><td>MRV_SENDER</td><td><a href="http://localhost:3005/">http://localhost:3005/</a></td><td>Demo</td></tr><tr><td>TOPIC_VIEWER</td><td><a href="http://localhost:3006/">http://localhost:3006/</a></td><td>Demo</td></tr><tr><td>API_DOCS</td><td><a href="http://localhost:3001/">http://localhost:3001/</a></td><td>Demo</td></tr></tbody></table>


# Launching Guardian

Once <http://localhost:3000> is launched, we need to first generate Operator ID and Operator Key by clicking on Generate button as shown below:

<figure><img src="/files/tfNmZx1kFGvZ8Gzf8ozL" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Note: If OPERATORID and OPERATOR KEY are added in .env file, we can click on Generate button directly without entering the details again in the UI.
{% endhint %}

Once you generated Operator ID and Operator Key, we can either click on Next or restore the Data, by selecting Restore Data from the Next button dropdown to setup Registry as shown below.

**Note**: Restore Data can be restored from Hedera if data is available for setting up the Registry.

<figure><img src="/files/uYzjPITOsuHFl7PzHxP7" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
**Limitations on restoring the data:**\
1\. The state of policy workflows is not persisted onto any decentralised storage used by Guardian (such as IPFS and/or Hedera blockchain), and therefore not available for restoring. This means that while all artifacts produced by projects and their respective Policy workflows will be discovered and made accessible through the restored Guardian, the policy execution state will not be restored.

2\. Similarly, dynamic filled ‘options’ from VCs is not available at restoration time. This results in the limitation that some document grids will not be restored.
{% endhint %}

If Next is clicked, we need to manually setup the Registry or if Restore Data is clicked, it is filled automatically.

![](/files/Nm7o7ZR7YhAJrZiIH0Gm)

**Note:** The above fields in UI are mandatory only for this default Schema.

The Format of the Standard Registry Hello World Message is as follows:

```
{
	'type': 'Standard Registry',
	'status':'ISSUE'
	'id': '35c5d340-1a93-475d-9659-818bb77d45df',
	'did': 'did:hedera:testnet:vzN41A2bMhvYGhg7oCMoo5UAzQ6PCTq4VTQaNPE1uPG;hedera:testnet:tid=0.0.3423402',
	'action': 'Init',
	'topicId': '0.0.34234020',
	'lang': 'en-US',
    'attributes' : {
    	'ISIC': '051 062',
    	'geography' : 'USA CAN EU AUS',
    	'law': 'USA',
    	'tags': 'VERRA iREC'
  }
}
```

Where the list of `attributes` is extendable, and all attributes in it are **optional**.

#### Standard Registry Message Parameters

<table><thead><tr><th width="305.3333333333333">Parameter</th><th width="210">Purpose</th><th>Example</th></tr></thead><tbody><tr><td>type</td><td>Account Type</td><td>Standard Registry</td></tr><tr><td>status</td><td>status of the message</td><td>ISSUE</td></tr><tr><td>id</td><td>Message ID</td><td>35c5d340-1a93-475d-9659-818bb77d45df</td></tr><tr><td>did</td><td>Hedera DID</td><td>did:hedera:testnet:vzN41A2bMhvYGhg7oCMoo5UAzQ6PCTq4VTQaNPE1uPG</td></tr><tr><td>action</td><td>Action Type</td><td>Init</td></tr><tr><td>topicId</td><td>Standard Registry Message Topic ID</td><td>0.0.34234020</td></tr><tr><td>lang</td><td>Language</td><td>ENG</td></tr><tr><td>ISIC</td><td>ISIC code</td><td>051</td></tr><tr><td>geography</td><td>Location</td><td>USA</td></tr><tr><td>law</td><td>Country Law</td><td>USA</td></tr><tr><td>tags</td><td>Policy Tags</td><td>Verra, iREC</td></tr></tbody></table>

### INITIALIZATION\_TOPIC\_ID for different Hedera Networks

| Network    | INITIALIZATION\_TOPIC\_ID |
| ---------- | ------------------------- |
| Mainnet    | 0.0.1368856               |
| Testnet    | 0.0.1960                  |
| Previewnet | 0.0.10071                 |

### RETIRE\_CONTRACT\_FILE\_ID and WIPE\_CONTRACT\_FILE\_ID for different Hedera Networks

<table><thead><tr><th width="146">Network</th><th width="258">RETIRE_CONTRACT_FILE_ID</th><th>WIPE_CONTRACT_FILE_ID</th></tr></thead><tbody><tr><td>Mainnet</td><td>0.0.5344116</td><td>0.0.5344170</td></tr><tr><td>Testnet</td><td>0.0.2219</td><td>0.0.2235</td></tr></tbody></table>

### **How to Deploy Contracts on Mainnet using your own account:**

**Note:** If you wish you have an option to deploy your own instances (from an account that your organization controls - e.g. an ‘official’ account of your organization). We have created scripts for easy deployment you can use. In this case the following procedure needs to be followed:

1. Navigate to `./guardian-cli`folder.
2. Execute `npm install` followed by `npm run build` and `npm i -g`
3. Now the scripts are ready, and you can execute at the level of the `guardian-cli` folder
4. RETIRE contract deployment:

`guardian-cli deploy-contract-file ../contracts/retire/Retire.sol Retire {account} {key} -n {network}`

5. WIPE contract deployment:

`guardian-cli deploy-contract-file ../contracts/wipe/Wipe.sol Wipe {account} {key} -n {network}`

Where:

* `account` - accound ID in hedera
* `key` - its private key
* `network` - the target network (testnet, mainnet, previewnet), by default it uses testnet

The contract file identifier will be printed out in the terminal.


# How to perform Unit Tests?

To run **guardian-service** unit tests, following commands needs to be executed:

```
cd guardian-service 
npm run test
```

It is also an ability to run Hedera network test only. To do that, the following command needs to be executed:

```
npm run test:network
```

To run stability tests (certain transactions will be executed 10 times each), the following command needs to be executed:

```
npm run test:stability
```

To run **message-broker** unit tests, following commands needs to be executed:

```
cd message-broker
npm run test
```


# How to Configure Hedera Local Node

1. [Step By Step Process](#step-by-step-process)
2. [Demo Video](#demo-video)

### Step By Step Process

1. Install a Hedera Local Network following the [official documentation](https://github.com/hashgraph/hedera-local-node#docker)
2. Configure Guardian's configuration files `.env/.env.docker` accordingly:

```
OPERATOR_ID=""
OPERATOR_KEY=""
LOCALNODE_ADDRESS="11.11.11.11"
LOCALNODE_PROTOCOL="http"
HEDERA_NET="localnode"
```

{% hint style="info" %}
Note:

1. Set **LOCALNODE\_ADDRESS** to the IP address of your local node instance. The value above is given as example.

2. Set **HEDERA\_NET** to **localnode**. If not specified, the default value is **testnet.**

3. Configure **OPERATOR\_ID** *and* **OPERATOR\_KEY** accordingly with your local node configuration.

4. Remove **INITIALISATION\_TOPIC\_ID** as the topic will be created automatically.

5. Set **LOCALNODE\_PROTOCOL** to **http** or **https** accordingly with your local node configuration (It uses HTTP by default).
   {% endhint %}

6. OPERATOR\_ID: The ID of the operation

7. OPERATOR\_Key: Private key of the operator\_

8. LOCALNODE\_ADDRESS : The address of the localnode server. This can be its IP address or a domain name

9. LOCALNODE\_PROTOCOL : Communication protocol for interactions with the local node, can be http or https.

10. HEDERA\_NET : Type of the Hedera node to transact.

### Demo Video

[Youtube](https://www.youtube.com/watch?v=EpCOI31iMoI\&list=PLnld0e1pwLhqdR0F9dusqILDww6uZywwR\&index=1)


# How to Configure HashiCorp Vault

1. Configure .env/.env.docker files in **auth-service** folder

<pre><code><strong>VAULT_PROVIDER = "hashicorp"
</strong></code></pre>

{% hint style="info" %}
**Note**: VAULT\_PROVIDER can be set to "database" or "hashicorp" to select Database instance or a hashicorp vault instance correspondingly.
{% endhint %}

If the VAULT\_PROVIDER value is set to "hashicorp" the following 3 parameters should be configured in **auth-service** folder.

1. HASHICORP\_ADDRESS : <http://localhost:8200> for using local vault. For remote vault, we need to use the value from the configuration settings of Hashicorp vault service.
2. HASHICORP\_TOKEN : the token from the Hashicorp vault.
3. HASHICORP\_WORKSPACE : this is only needed when we are using cloud vault for Hashicorp. Default value is "admin".

2\. Hashicorp should be configured with the created Key-Value storage, named "secret" by default, with the settingKey=\<value> records for the following keys:

1. OPERATOR\_ID
2. OPERATOR\_KEY
3. IPFS\_STORAGE\_API\_KEY

{% hint style="info" %}
**Note:** These records in vault will be created automatically if there are environment variables with the matching names.
{% endhint %}

#### How to import existing user keys from DB into the vault:

During Guardian services initialization, we need to set the following configuration settings in **auth-service** folder:

```
IMPORT_KEYS_FROM_DB = 1
VAULT_PROVIDER = "hashicorp"
```


# How to create Operator ID and Operator Key

1. [Step by Step Process](#step-by-step-process)
2. [Demo Video](#demo-video)

### Step by Step Process

Following are the steps to follow to create Operator ID and Operator Key:

1. We need to create an account in Hedera Testnet Portal : <https://portal.hedera.com/login>

<figure><img src="/files/PWcLkoTdiH6A4nDcAVN2" alt=""><figcaption><p>Login Screen</p></figcaption></figure>

If not logged in, we need to Sign Up as shown below:

<figure><img src="/files/MUYEHoCw9TCSZyHnbVKA" alt=""><figcaption></figcaption></figure>

2\. Once logged in successfully, we will get account ID, Private Key and Public Key of Hedera Testnet.

<figure><img src="/files/2l015tJ0ydjfmAihcPim" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Note: By Default, Testnet network keys are displayed. we can change the network by selecting network from the dropdown.
{% endhint %}

<figure><img src="/files/QxgJxomS77RsVQ2yNYlU" alt=""><figcaption></figcaption></figure>

3\. After selecting required network, copy accountId and privateKey and paste it as Operator ID and Operator Key respectively in `guardian-service/.env` or `guardian-service/.env/docker`.

### Demo Video

[Youtube](https://www.youtube.com/watch?v=oXJiyXF1zM4\&list=PLnld0e1pwLhqdR0F9dusqILDww6uZywwR\&index=7)


# How to generate Web3.Storage API values

For additional information, please visit: <https://web3.storage/docs/#quickstart>

1. [Step By Step Process](#step-by-step-process)
2. [Demo Video](#demo-video)

### Step By Step Process

Following are the steps to follow to generate Web3.Storage API values:

1. Create an account on [https://web3.storage](https://web3.storage/), please specify the email you have access to as the account authentication is based on the email validation. Make sure to follow through the registration process to the end, choose an appropriate billing plan for your needs (e.g. 'starter') and enter your payment details.

<figure><img src="/files/JXsW7MyqPiqHzIlTBrUj" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/GhYOIXbzSKTH7JNWT03X" alt=""><figcaption></figcaption></figure>

2\. Install w3cli as described in the [corresponding section](https://web3.storage/docs/w3cli/#install) of the web3.storage documentation.

**You'll need** [**Node**](https://nodejs.org/en) **version 18 or higher, with NPM version 7 or higher to complete the installation**

You can check your local versions like this:

```
node --version && npm --version
```

Install the `@web3-storage/w3cli` package with `npm`

```
npm install -g @web3-storage/w3cli
```

3\. Create your 'space' as described in the ['Create your first space'](https://web3.storage/docs/w3cli/#create-your-first-space) section of the documentation.

```
w3 space create
```

4. Execute the following to set the Space you intend on delegating access to:

```
w3 space use
```

5. Execute the following command to retrieve your Agent private key and DID:

```
npx ucan-key ed
```

{% hint style="info" %}
**Note:** The private key (starting with `Mg...`) is the value to be used in the environment variable `IPFS_STORAGE_KEY`.
{% endhint %}

6. Retrieve the IPFS\_STORAGE\_PROOF by executing the following:

```
w3 delegation create <did_from_ucan-key_command_above> | base64
```

The output of this command is the value to be used in the environment variable `IPFS_STORAGE_PROOF`.

**To summarize, the process of configuring delegated access to the w3up API consists of execution of the following command sequence:**

1. `w3 login`
2. `w3 space create`
3. `w3 space use`
4. `npx ucan-key ed`
5. `w3 delegation`

### Demo Video

[Youtube](https://www.youtube.com/watch?v=q5OK9VWBn8Y\&list=PLnld0e1pwLhqdR0F9dusqILDww6uZywwR\&index=12)


# How to Change Explorer URL

To make changes in the Explorer, we need to change some parameters in environment settings on UI. explorerSettings, which contains url (with network, type, value variables) , networkMap, typeMap (networkMap and typeMap helps to resolve api path on different explorers) as shown:

<figure><img src="/files/WipY5CEVx0uvmdcLvv57" alt=""><figcaption></figcaption></figure>

As we see the above demonstrates setting of Ledger Works explorer.

{% hint style="info" %}
**Note: By default, we use HashScan explorer.**
{% endhint %}

#### To switch from HashScan to Dragon Glass we need to make following changes:

1. Change the url to [https://${network}.dragonglass.me/hedera/${type}/${value}](https://${network}.dragonglass.me/hedera/$%7Btype%7D/$%7Bvalue%7D)
2. Change networkMap mainnet to app

<figure><img src="/files/lndmkOk9KcUPvU84FVJs" alt=""><figcaption></figcaption></figure>


# How to Restore Account from Database/Hashicorp Vault during Setup

For backup all data, we need to create dump of all used mongodb databases and hashicorp vault (if it use)

#### Mongo DB:

Mongo DB databases set in .env (.env.docker) files or via environment variables named DB\_DATABASE Default names:

* auth-service - auth\_db
* guardian-service - guardian\_db
* logger-service (not necessary) - logger\_db

Example using mongo utils:

Creating dump:

```
mongodump --db auth_db --out ./dump
mongodump --db guardian_db --out ./dump
mongodump --db logger_db --out ./dump
```

Restoring dump:

```
mongorestore --db auth_db ./dump/auth_db
mongorestore --db guardian_db ./dump/guardian_db
mongorestore --db logger_db ./dump/logger_db
```

#### HashiCorp Vault:

For HashiCorp vault backup and restore use this instructions: <https://developer.hashicorp.com/vault/tutorials/standard-procedures/sop-backup>


# Frameworks/Libraries

The Guardian solution is built with the following major frameworks/libraries.

**Backend**

* [NodeJS](https://nodejs.org/)
* [MongoDB](https://www.mongodb.com/)
* [Express](https://expressjs.com/)
* [Nats](https://nats.io/)
* [MikroORM](https://mikro-orm.io/)
* [W3C VC-JS-HTTP](https://w3c.github.io/vc-data-model/)
* [Transmute](https://github.com/transmute-industries/verifiable-data/tree/main/packages/vc.js)
* [MathJS](https://mathjs.org)
* [Web3.Storage](https://github.com/web3-storage/web3.storage)
* [NestJS](https://nestjs.com/)
* [Nginx](https://www.nginx.com/)
* [Hedera network](https://portal.hedera.com/login)

**Frontend**

* [Angular](https://angular.io/)
* [crypto-browserify](https://www.npmjs.com/package/crypto-browserify)


# VM0033 API Walkthrough

Below is complete API flow to execute Verra VM0033 Methodology:

### 1. Policy Preparing from Standard Registry (SR) side:

#### 1.1 Login by SR

<figure><img src="/files/76UPpMolTXwjBoVPcEdA" alt=""><figcaption></figcaption></figure>

To login, the user must request a refresh token:

<mark style="color:green;">`POST`</mark>`http://localhost:4200/api/v1/accounts/login/` with credentials in body:

```json5
   {
      "username":"StandardRegistry",
      "password":"test"
   }
```

Successful response looks like:

```json5
{
   "username": "StandardRegistry",
   "did": "did:hedera:testnet:83JSEFhdaoZ4ougdVtCpAWXbsCP8hcuNpSZeEJ8GSins_0.0.6851752",
   "role": "STANDARD_REGISTRY",
   "refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9eyJpZCI6ImY0MGZiMDIzLWNlMzUtNDFmYS1hNzAxLTkyYjdmMmQ1MzQ5MiIsm5hbWUiOiJTdGFuZGFyZFJlZ2lzdHJ5IiwiZXhaXJlQXQiOjE3ODk0ODAxMzU2NTQsImlhdCI6MTc1Nzk0NDEzNX0Lr10b-in9SlAgTvKLwdypOVY8uANlAEJ1zNduHK8OpTxIUS-dBZ39OAZyr4sQRqsJYkxtRAiItYOgS45EvPBP1u-XMAzS2CqeM2lu2N81k53Sy6RQrDmpK_YIDMmRWeWMulJJ5IWtSe3kga4hwbYs0SyTXRkuVfoG-SnAlmTgA",
   "weakPassword": false
}
```

**With the `refreshToken` from the response, you can obtain an access token, which is then used in the `authorization` header for each request:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/accounts/access-token/`

```json5
{
   "refreshToken":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9. eyJpZCI6Ijc4NWRmODljLTY2OTQtNGIwMC04OWRlLTllZjJkMjZkY2RmZiIsIm5hbWUiOiJTdGFuZGFyZFJlZ2lzdHJ5IiwiZXhwa XJlQXQiOjE3ODk0ODAwNjg5NDAsImlhdCI6MTc1Nzk0NDA2OH0. NdCEXa-29qI79XcKN51P12rqLDsH2CvUUqWrS1OBTaNAetiuwYOkvhpx67RblauILY3VmxHf3kYqxhn93RmD5tjhh8G4AM4KCErGOdknUbhc_wTpM2gha_xkljNw4QP-x5rbPRXpK6f3DhjP21gwTmMpMiF9kVz1r6MikelmWLc"
}
```

Successful response looks like:

```json5
{
   "accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IlN0YW5kYXJkUmVnaXN0cnkiLCJkaWQiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ODNKU0VGaGRhb1o0b3VnZFZ0Q3BBV1hic0NQOGhjdU5wU1plRUo4R1NpbnNfMC4wLjY4NTE3NTIiLCJyb2xlIjoiU1RBTkRBUkRfUkVHSVNUUlkiLCJleHBpcmVBdCI6MTc4OTQ4MDA2ODk3NiwiaWF0IjoxNzU3OTQ0MDY4fQ.ZESg2mjHRGHehoS-WAGvUJMekWsfqcgVCYxRdLfnuKQ7AyYdypVXguNZzSJnu5fcaP-zOTWH7C_Dhs_w7Jx4BEQOhv7Cjd0_XPI9hluTZ13VzkrkkWkwpavCtCn2YM4OvbIPSVtBvZI4u2unkfhLMTOx17Vf0S-moYq-z9cQv2I"
}
```

#### 1.2 VM0033 Policy Importing

<figure><img src="/files/OtD4pVng0S6ISm6WeP6R" alt=""><figcaption></figcaption></figure>

**To import a policy, send a request with the policy’s `messageId` in the body:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/import/message/`

with body:

```json5
{
   "messageId":"1755735271.024933000"
} 
```

Successful response looks like:

```json5
{
 "createDate": "2025-09-15T13:48:51.980Z",
 "uuid": "0aa2451e-70e6-49eb-a277-b0217c7699e4",
 "name": "VM0033-v1.0.3_8_14_1755731415625",
 "description": "This methodology outlines procedures for estimating net greenhouse gas (GHG) emission reductions and removals from tidal wetland restoration projects.",
 "status": "DRAFT",
 "creator": "did:hedera:testnet:83JSEFhdaoZ4ougdVtCpAWXbsCP8hcuNpSZeEJ8GSins_0.0.6851752",
 "owner": "did:hedera:testnet:83JSEFhdaoZ4ougdVtCpAWXbsCP8hcuNpSZeEJ8GSins_0.0.6851752",
 "policyRoles": [
     "Project_Proponent",
     "VVB"
 ],
 "policyGroups": [],
 "topicId": "0.0.6851810",
 "instanceTopicId": null,
 "policyTag": "Tag_1757944077340",
 "codeVersion": "1.5.1",
 "tools": [
     {
         "name": "AR Tool 05(3.0.2)",
         "topicId": "0.0.5987758",
         "messageId": "1747119324.564353000"
     },
     {
         "name": "AR Tool 14(5.0.7)",
         "topicId": "0.0.6471034",
         "messageId": "1753864157.889867000"
     }
 ],
 "_id": "68c952870fd12e530dddadf8",
 "userRoles": [
     "Administrator"
 ],
 "userGroups": [],
 "userRole": "Administrator",
 "userGroup": null,
 "tests": [],
 "id": "68c952870fd12e530dddadf8"
}
```

#### 1.3 Policy Publishing

<figure><img src="/files/ilzTIm0TEozsbuCeabXw" alt=""><figcaption></figcaption></figure>

**To publish a policy, use the id field from the previous step in the request:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/publish/`

with body, field `policyAvailability` optional:

```json5
{
   "policyVersion":"1.2.5",
   "policyAvailability":"private"
}
```

Successful response looks like:

```json5
{
 "isValid": true,
 "errors": {
     "errors": [],
     "blocks": [ 
         there are a list of blocks, one of them for example:           
         {
             "id": "9f25ddec-772c-4d3b-8268-29db09c45f8d",
             "name": "buttonBlock",
             "errors": [],
             "isValid": true
         }
     ],
     "modules": [],
     "tools": [
         there are a list of tools, one of them for example:
         {
             "errors": [],
             "blocks": [
                 {
                     "id": "b7984eab-893a-497f-ba73-3e6d4c0b7ce0",
                     "name": "extractDataBlock",
                     "errors": [],
                     "isValid": true
                 },
                 {
                     "id": "52974f49-497d-403b-9616-829da32590fe",
                     "name": "customLogicBlock",
                     "errors": [],
                     "isValid": true
                 },
                 {
                     "id": "16f57f36-48db-4989-adb1-ddb276fc23f1",
                     "name": "extractDataBlock",
                     "errors": [],
                     "isValid": true
                 }
             ],
             "tools": [],
             "id": "f52b313c-219c-498b-9ff2-05476753483c",
             "isValid": true
         },
     ],
     "isValid": true
 },
 "policies": [
     {
         "createDate": "2025-09-15T13:48:51.980Z",
         "uuid": "0aa2451e-70e6-49eb-a277-b0217c7699e4",
         "name": "VM0033-v1.0.3_8_14_1755731415625",
         "version": "1.2.5",
         "description": "This methodology outlines procedures for estimating net greenhouse gas (GHG) emission reductions and removals from tidal wetland restoration projects.",
         "status": "PUBLISH",
         "creator": "did:hedera:testnet:83JSEFhdaoZ4ougdVtCpAWXbsCP8hcuNpSZeEJ8GSins_0.0.6851752",
         "owner": "did:hedera:testnet:83JSEFhdaoZ4ougdVtCpAWXbsCP8hcuNpSZeEJ8GSins_0.0.6851752",
         "policyRoles": [
             "Project_Proponent",
             "VVB"
         ],
         "policyGroups": [],
         "topicId": "0.0.6851810",
         "instanceTopicId": "0.0.6851818",
         "policyTag": "Tag_1757944077340",
         "messageId": "1757944246.325090000",
         "codeVersion": "1.5.1",
         "tools": [
             {
                 "name": "AR Tool 05(3.0.2)",
                 "topicId": "0.0.5987758",
                 "messageId": "1747119324.564353000"
             },
             {
                 "name": "AR Tool 14(5.0.7)",
                 "topicId": "0.0.6471034",
                 "messageId": "1753864157.889867000"
             }
         ],
         "_id": "68c952870fd12e530dddadf8",
         "userRoles": [
             "Administrator"
         ],
         "userGroups": [],
         "userRole": "Administrator",
         "userGroup": null,
         "tests": [],
         "id": "68c952870fd12e530dddadf8"
     }
  ]
}
```

#### 1.4 Assign Policy to VVB and Project Proponent (PP) Users

<figure><img src="/files/P6z20Ok4l83hUkQar130" alt=""><figcaption></figcaption></figure>

**To assign a policy to a user, include the username in the request body, and set the `policyId` field to the id value from the policy importing step:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/permissions/users/{username}/policies/assign/`

For example:

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/permissions/users/ProjectProponent/policies/assign/`

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/permissions/users/VVB/policies/assign/`

with body, where in policyId using "id" field from policy importing step:

```json5
{
   "policyIds":["68c952870fd12e530dddadf8"],
   "assign":true
}
```

Successful response looks like:

```json5
   true
```

### 2. Token associate and grant KYC

#### 2.1 Login as SR

#### 2.1.1 Associate Token for PP

**Before associating, obtain the `tokenId` by extracting it from the token linked to the policy:**

<mark style="color:red;">`GET`</mark> `http://localhost:4200/api/v1/tokens`

Successful response looks like:

```json5
   [
      {
         "id":"68c819368a003cc1fb32e9b6",
         "tokenId":"0.0.6851817",
         "tokenName":"VCU",
         "tokenSymbol":"VCU",
         "tokenType":"non-fungible",
         "decimals":0,
         "policyId":null,
         "enableAdmin":true,
         "enableFreeze":true,
         "enableKYC":true,
         "enableWipe":true,
         "associated":false,
         "balance":null,
         "hBarBalance":null,
         "frozen":null,
         "kyc":null,
         "policies":["VM0033-v1.0.3_8_14_1755731415625 (1.2.5)"],
         "policyIds":["68c952870fd12e530dddadf8"],
         "canDelete":false
      }
   ]
```

We need to extract `tokenId` from token, which linked with our policy(`policyId` from step 1.2 equal with `policyIds` in response)

**Send a request with the `tokenId` from the previous response:**

<mark style="color:green;">`PUT`</mark> `http://localhost:4200/api/v1/tokens/0.0.6851817/associate`

Successful response looks like:

```json5
   {
      "tokenName":"VCU",
      "status":true
   }
```

#### 2.3 Login by PP

#### 2.3.1 Grant KYC Token by PP

**To grant a KYC token, send a request with the `tokenId` and the `username`:**

<mark style="color:green;">`PUT`</mark> `http://localhost:4200/api/v1/tokens/0.0.6851817/ProjectProponent/grant-kyc`

Successful response looks like:

```json5
   {
      "id":"68c819368a003cc1fb32e9b6",
      "tokenId":"0.0.6851817",
      "tokenName":"VCU",
      "tokenSymbol":"VCU",
      "tokenType":"non-fungible",
      "decimals":0,
      "policyId":null,
      "enableAdmin":true,
      "enableFreeze":true,
      "enableKYC":true,
      "enableWipe":true,
      "associated":true,
      "balance":"0",
      "hBarBalance":"4.78479825 ℏ",
      "frozen":false,
      "kyc":true
   }
```

### 3 Register PP in policy and create project description

#### 3.1 Login by PP

#### 3.2 Choose PP Role in Policy and Create Project Description

<figure><img src="/files/JgmZqrbV1lm8UWQ9QY9X" alt=""><figcaption></figcaption></figure>

**To choose a role in the policy, send a request with the role name in the body:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/Choose_Roles/blocks/`

with body:

```json5
   {
      "role":"Project_Proponent"
   }
```

Successful response looks like:

```json5
true
```

**To create a project description in the policy, send a request with the project description details. (The payload example is large and will be attached separately.):**

<figure><img src="/files/8mIk1r9UYG1mzjKXNYue" alt=""><figcaption></figcaption></figure>

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/add_project_bnt/blocks/`

```json5
body: {
   "document": *payload from file*,
   "ref": null
}
```

Successful response looks like:

```json5
{
"policyId": "68c952870fd12e530dddadf8",
"tag": "add_project_bnt",
"hash": "5ANJA6RqAxm8CE1LD6gXobZF4xh5JqSFoBgDPQ1LYprT",
"document": {
 "id": "urn:uuid:823784f9-b381-4baf-91b7-26f1eeac3313",
 "type": [
   "VerifiableCredential"
 ],
 "issuer": "did:hedera:testnet:DDyFMz36eN1cBEopW79DmCUYx75qK7fsohioqM1X72pn_0.0.6851752",
 "issuanceDate": "2025-09-15T13:52:53.318Z",
 "@context": [
   "https://www.w3.org/2018/credentials/v1",
   "ipfs://bafkreiaumw2eerg4g54l5lqlpl3osnrpw6qrhvfaooiivepuusanby7b5i"
 ],
 "credentialSubject":*there is payload from request*,
 "proof": {
   "type": "Ed25519Signature2018",
   "created": "2025-09-15T13:52:56Z",
   "verificationMethod": "did:hedera:testnet:DDyFMz36eN1cBEopW79DmCUYx75qK7fsohioqM1X72pn_0.0.6851752#did-root-key",
   "proofPurpose": "assertionMethod",
   "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..pq81MSFjH4-c0nEZWSO1TfbxOiP-jOtXEYhuU9JbCsW749jrBUm2Q3lqnHDgELPc9xKFi7rL3wwfuKHrDZl_DQ"
 }
},
"owner": "did:hedera:testnet:DDyFMz36eN1cBEopW79DmCUYx75qK7fsohioqM1X72pn_0.0.6851752",
"group": "4263ca60-ef8a-4fce-946d-e9242dc46278",
"hederaStatus": "NEW",
"signature": 0,
"type": "#d4b36968-9c0d-4a64-9d3f-59dc630bc1d4&1.0.0",
"schema": "#d4b36968-9c0d-4a64-9d3f-59dc630bc1d4&1.0.0",
"accounts": {
 "default": "0.0.6851803"
},
"relationships": null
}
```

**Wait for the request to finish processing:**

<figure><img src="/files/M0j8J45UZs1j6F4hULye" alt=""><figcaption></figcaption></figure>

<mark style="color:red;">`GET`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/project_grid_pp_2/blocks`

Waiting while `data.option.status` would be equal "Waiting to be Added":

```json5
{
"id": "599bc800-3413-4606-b770-563fcfdef5fb",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:10:55.134Z",
   "updateDate": "2025-09-16T12:10:55.321Z",
   "_propHash": "a436cf898f1337442cb7794381e292a8",
   "_docHash": "b9c75ab0e3f6c40fa0fd23a3de673e32",
   "hash": "6v8F2e4bLdf6yccg4XVh5BFHsDEm41aC36FnnofEWf3W",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "project",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_project_auto",
   "schema": "#6482c99e-4af8-4cd1-94e6-ee82d2284197&1.0.0",
   "option": {
     "status": "Waiting to be Added"
   },
   "relationships": [
     "1758024619.744335000",
     "1758024539.869960000"
   ],
   "owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
   "group": "5d49111f-c662-4494-ac71-35c4826f5684",
   "accounts": {
     "default": "0.0.6856932"
   },
   "tokens": null,
   "topicId": "0.0.6856972",
   "messageId": "1758024652.684467000",
   "messageHash": "CQ4LpNhuNA9MGv5HdmaAdLz3oT42wbTsxUE7VNzzEGSL",
   "messageIds": [
     "1758024652.684467000"
   ],
   "document": {
     "id": "urn:uuid:0ee4a666-7b8a-4857-afcc-b048aec177dc",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
     "issuanceDate": "2025-09-16T12:10:29.158Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],"credentialSubject": *there is huge payload*,
     "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:10:32Z",
       "verificationMethod": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..-czwVoPGwWiLFbo0xjcAgf9buHVqUdD59HKIJFZa-XbYk_2uSDaskCvQxpDrHlCJrwSe0BL76Gpb6UpQ-G9TCw"
     }
   },
   "documentFileId": "68c953cf7d1632a3d92d63e5",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c953cf7d1632a3d92d63dd",
   "__sourceTag__": "project_grid_pp_2_waiting_to_add_projects",
   "history": [
     {
       "labelValue": "Waiting to be Added",
       "created": "2025-09-16T12:10:55.533Z"
     }
   ],
   "id": "68c953cf7d1632a3d92d63dd"
 }
],
"blocks": [
 {
   "id": "5e1b4ecb-5860-4a53-a734-de96bbf45fe3",
   "uiMetaData": {
     "options": [],
     "title": "",
     "content": "Project Name"
   },
   "blockType": "filtersAddon"
 }
],
"commonAddons": [
 {
   "id": "1bec12bf-486d-4014-994a-ee0937a64ae9",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "1c88d5df-6519-496f-b02f-76de9ce3b0be",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "c1cd6720-6129-4c62-ae8f-4b850bb113b7",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "ad0aa831-b318-4e93-b6fa-eb01fef01f83",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "930d5a57-080e-4289-9fe7-3f71192e200f",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "f41365cf-a1c5-4394-bfda-a0d74e7f9bb1",
   "blockType": "historyAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.project_details.G5",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Status",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": "170px"
 },
 {
   "title": "Assign",
   "name": "assignedTo",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "assign_vvb",
   "bindGroup": "project_grid_pp_2_waiting_to_validate_projects",
   "width": "150px"
 },
 {
   "title": "Assign",
   "name": "assignedTo",
   "tooltip": "",
   "type": "text",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "",
   "bindGroup": "project_grid_pp_2_validated_projects",
   "width": "150px"
 },
 {
   "title": "Add Report",
   "name": "report",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "add_report_bnt",
   "bindGroup": "project_grid_pp_2_validated_projects",
   "width": "150px"
 },
 {
   "title": "View Reports",
   "name": "document.credentialSubject.0.id",
   "tooltip": "",
   "type": "button",
   "action": "link",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "report_grid_pp",
   "content": "View Reports",
   "bindGroup": "project_grid_pp_2_validated_projects",
   "width": "150px"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_project_pp_btn",
   "width": "100px",
   "bindGroup": "project_grid_pp_2_waiting_to_add_projects"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_project_pp_btn",
   "width": "100px",
   "bindGroup": "project_grid_pp_2_waiting_to_validate_projects"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_project_pp_btn",
   "width": "100px",
   "bindGroup": "project_grid_pp_2_validated_projects_own"
 }
],
"viewHistory": true
}
```

### 4 Register VVB

#### 4.1 Login by VVB

#### 4.2 Choose VVB Role

<figure><img src="/files/jTCMPQRKjv2lb1nQOHAc" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/g6wJ29LvJL05THYEARCr" alt=""><figcaption></figcaption></figure>

**To choose a role in the policy, send a request with the role name in the body:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/Choose_Roles/blocks/`

with body:

```json5
   {
      "role":"VVB"
   }
```

Successful response looks like:

```json5
true
```

**To create a VVB in the policy, send a request with the VVB name in the body:**

<figure><img src="/files/PIWwku71jcrihnq9BBJi" alt=""><figcaption></figcaption></figure>

`POST http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/create_new_vvb/blocks`

with body:

```json5
{
   "document":
      {
         "field0":"TestingVVBName"
      },
   "ref":null
}
```

Successful response looks like:

```json5
{
"policyId": "68c952870fd12e530dddadf8",
"tag": "create_new_vvb",
"hash": "7vC6FAPkZS1oTySBgef3M7iwWAJViVzMHzc8eBVDKAaP",
"document": {
 "id": "urn:uuid:f56a4268-aeff-4ba5-b61b-f242b2c4c966",
 "type": [
   "VerifiableCredential"
 ],
 "issuer": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
 "issuanceDate": "2025-09-16T12:09:21.143Z",
 "@context": [
   "https://www.w3.org/2018/credentials/v1",
   "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
 ],
 "credentialSubject": [
   {
     "field0": "TestingVVBName",
     "policyId": "68c952870fd12e530dddadf8",
     "guardianVersion": "3.3.0",
     "@context": [
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "id": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
     "type": "de418a5a-5df8-44f0-aa31-ff834b980836&1.0.0"
   }
 ],
 "proof": {
   "type": "Ed25519Signature2018",
   "created": "2025-09-16T12:09:23Z",
   "verificationMethod": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936#did-root-key",
   "proofPurpose": "assertionMethod",
   "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19.._OZaqFpfxkT1jxWxdlQBqB9WDCgrOm31QyOjBk16LX6lNulMtMvwxtpjDuFTUyK5tv-6QViYId3ZyiadYqwCDg"
 }
},
"owner": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
"group": "2c6c93e9-d089-4518-9f66-e548df9e0cac",
"hederaStatus": "NEW",
"signature": 0,
"type": "#de418a5a-5df8-44f0-aa31-ff834b980836&1.0.0",
"schema": "#de418a5a-5df8-44f0-aa31-ff834b980836&1.0.0",
"accounts": {
 "default": "0.0.6856934"
},
"relationships": null
}
```

**Wait until the title is equal to “Waiting for approval”:**

<figure><img src="/files/EkpGKMkGy9Cb3YC2a48P" alt=""><figcaption></figcaption></figure>

<mark style="color:red;">`GET`</mark>` `` ``http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/new_VVB/blocks `

Waiting while `blocks.uiMetaData.title` would be equal "Waiting for approval":

```json5
{
"id": "9a184131-9eaa-44cf-bc93-b2c18bc141b1",
"blockType": "interfaceStepBlock",
"actionType": "remote",
"readonly": false,
"uiMetaData": {
 "type": "blank"
},
"index": 3,
"blocks": [
 null,
 null,
 null,
 {
   "uiMetaData": {
     "title": "Waiting for approval",
     "description": "Waiting for approval",
     "type": "text"
   },
   "content": "informationBlock",
   "blockType": "informationBlock",
   "id": "5f70b00e-f81d-4abd-b69d-24696943031d"
 },
 null,
 null,
 null,
 null,
 null,
 null,
 null,
 null,
 null,
 null
]
}
```

### 5 Project Flow

#### 5.1 Login by SR

#### 5.2 Add Project

<figure><img src="/files/6ZftfXbjz4gl0oFQb4DO" alt=""><figcaption></figcaption></figure>

**Get the project reference by saving the response data:**

<mark style="color:red;">`GET`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/project_grid_verra/blocks`

Change the project status from “Waiting to be Added” to “Waiting to Validate”:

<figure><img src="/files/Yad36hPopBIyyMJ7xlFK" alt=""><figcaption></figcaption></figure>

```json5
{
"id": "c107ac28-caa5-4cd1-828d-397e292880f7",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:10:55.134Z",
   "updateDate": "2025-09-16T12:10:55.321Z",
   "_propHash": "a436cf898f1337442cb7794381e292a8",
   "_docHash": "b9c75ab0e3f6c40fa0fd23a3de673e32",
   "hash": "6v8F2e4bLdf6yccg4XVh5BFHsDEm41aC36FnnofEWf3W",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "project",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_project_auto",
   "schema": "#6482c99e-4af8-4cd1-94e6-ee82d2284197&1.0.0",
   "option": {
     "status": "Waiting to be Added"
   },
   "relationships": [
     "1758024619.744335000",
     "1758024539.869960000"
   ],
   "owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
   "group": "5d49111f-c662-4494-ac71-35c4826f5684",
   "accounts": {
     "default": "0.0.6856932"
   },
   "tokens": null,
   "topicId": "0.0.6856972",
   "messageId": "1758024652.684467000",
   "messageHash": "CQ4LpNhuNA9MGv5HdmaAdLz3oT42wbTsxUE7VNzzEGSL",
   "messageIds": [
     "1758024652.684467000"
   ],
   "document": {
     "id": "urn:uuid:0ee4a666-7b8a-4857-afcc-b048aec177dc",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
     "issuanceDate": "2025-09-16T12:10:29.158Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject": *there is huge payload*,
     "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:10:32Z",
       "verificationMethod": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..-czwVoPGwWiLFbo0xjcAgf9buHVqUdD59HKIJFZa-XbYk_2uSDaskCvQxpDrHlCJrwSe0BL76Gpb6UpQ-G9TCw"
     }
   },
   "documentFileId": "68c953cf7d1632a3d92d63e5",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c953cf7d1632a3d92d63dd",
   "__sourceTag__": "project_grid_verra_waiting_to_add_projects",
   "id": "68c953cf7d1632a3d92d63dd"
 }
],
"blocks": [
 {
   "id": "451fdcab-bdf3-4e21-a018-9e06b6bb63e8",
   "uiMetaData": {
     "options": [],
     "content": "Project Name"
   },
   "blockType": "filtersAddon"
 }
],
"commonAddons": [
 {
   "id": "3cc1e78e-4a8c-4979-b76d-181edfed61e5",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "31ec045e-430c-47b9-ab61-ccf8cd1b389f",
   "blockType": "documentsSourceAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.project_details.G5",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Status",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": "150px"
 },
 {
   "title": "Add",
   "name": "add",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "add_project",
   "bindGroup": "project_grid_verra_waiting_to_add_projects",
   "width": "150px"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link",
   "width": "150px"
 }
],
"type": "blank",
"viewHistory": false
}
```

**Send the updated project data in the request:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/add_project/blocks`

With body:

```json5
{
   "document": *changed project data*,
   "tag": "Option_0"
}
```

#### 5.3 Login by PP

#### 5.4 Assign Project

<figure><img src="/files/4JuZYnmFRb2WkSjZGinh" alt=""><figcaption></figcaption></figure>

**Get the project reference by saving the response data:**

<mark style="color:red;">`GET`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/project_grid_pp_2/blocks`

Create and fill the field with the VVB DID:

```json5
{
"id": "599bc800-3413-4606-b770-563fcfdef5fb",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:10:55.134Z",
   "updateDate": "2025-09-16T12:11:19.572Z",
   "_propHash": "145fdf530827acf5761b3050ea701ab7",
   "_docHash": "b9c75ab0e3f6c40fa0fd23a3de673e32",
   "hash": "6v8F2e4bLdf6yccg4XVh5BFHsDEm41aC36FnnofEWf3W",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "project",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_added",
   "schema": "#6482c99e-4af8-4cd1-94e6-ee82d2284197&1.0.0",
   "option": {
     "status": "Waiting to Validate"
   },
   "relationships": [
     "1758024619.744335000",
     "1758024539.869960000"
   ],
   "owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
   "group": "5d49111f-c662-4494-ac71-35c4826f5684",
   "accounts": {
     "default": "0.0.6856932"
   },
   "tokens": null,
   "topicId": "0.0.6856972",
   "messageId": "1758024652.684467000",
   "messageHash": "CQ4LpNhuNA9MGv5HdmaAdLz3oT42wbTsxUE7VNzzEGSL",
   "messageIds": [
     "1758024652.684467000"
   ],
   "document": {
     "id": "urn:uuid:0ee4a666-7b8a-4857-afcc-b048aec177dc",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
     "issuanceDate": "2025-09-16T12:10:29.158Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject": *there is huge payload*,
     "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:10:32Z",
       "verificationMethod": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..-czwVoPGwWiLFbo0xjcAgf9buHVqUdD59HKIJFZa-XbYk_2uSDaskCvQxpDrHlCJrwSe0BL76Gpb6UpQ-G9TCw"
     }
   },
   "documentFileId": "68c953e77d1632a3d92d63ff",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c953cf7d1632a3d92d63dd",
   "__sourceTag__": "project_grid_pp_2_waiting_to_validate_projects",
   "history": [
     {
       "labelValue": "Waiting to be Added",
       "created": "2025-09-16T12:10:55.533Z"
     },
     {
       "labelValue": "Waiting to Validate",
       "created": "2025-09-16T12:11:19.704Z"
     }
   ],
   "id": "68c953cf7d1632a3d92d63dd"
 }
],
"blocks": [
 {
   "id": "5e1b4ecb-5860-4a53-a734-de96bbf45fe3",
   "uiMetaData": {
     "options": [],
     "title": "",
     "content": "Project Name"
   },
   "blockType": "filtersAddon"
 }
],
"commonAddons": [
 {
   "id": "1bec12bf-486d-4014-994a-ee0937a64ae9",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "1c88d5df-6519-496f-b02f-76de9ce3b0be",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "c1cd6720-6129-4c62-ae8f-4b850bb113b7",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "ad0aa831-b318-4e93-b6fa-eb01fef01f83",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "930d5a57-080e-4289-9fe7-3f71192e200f",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "f41365cf-a1c5-4394-bfda-a0d74e7f9bb1",
   "blockType": "historyAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.project_details.G5",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Status",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": "170px"
 },
 {
   "title": "Assign",
   "name": "assignedTo",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "assign_vvb",
   "bindGroup": "project_grid_pp_2_waiting_to_validate_projects",
   "width": "150px"
 },
 {
   "title": "Assign",
   "name": "assignedTo",
   "tooltip": "",
   "type": "text",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "",
   "bindGroup": "project_grid_pp_2_validated_projects",
   "width": "150px"
 },
 {
   "title": "Add Report",
   "name": "report",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "add_report_bnt",
   "bindGroup": "project_grid_pp_2_validated_projects",
   "width": "150px"
 },
 {
   "title": "View Reports",
   "name": "document.credentialSubject.0.id",
   "tooltip": "",
   "type": "button",
   "action": "link",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "report_grid_pp",
   "content": "View Reports",
   "bindGroup": "project_grid_pp_2_validated_projects",
   "width": "150px"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_project_pp_btn",
   "width": "100px",
   "bindGroup": "project_grid_pp_2_waiting_to_add_projects"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_project_pp_btn",
   "width": "100px",
   "bindGroup": "project_grid_pp_2_waiting_to_validate_projects"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_project_pp_btn",
   "width": "100px",
   "bindGroup": "project_grid_pp_2_validated_projects_own"
 }
],
"viewHistory": true
}
```

**Send the updated project data in the request:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/assign_vvb/blocks`

With body:

```json5
*changed project data*
```

#### 5.5 Login by VVB

#### 5.6 Approve Project

<figure><img src="/files/NXclkHUOC3hypoOyGgoR" alt=""><figcaption></figcaption></figure>

**Wait until the project status changes to “Waiting to Validate”:**

<mark style="color:red;">`GET`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/project_grid_vvb/blocks`

Save the response data as a reference and update the status to “Validated”

<figure><img src="/files/yNTyXGVQWsYLYMlKLWNn" alt=""><figcaption></figcaption></figure>

```json5
{
"id": "302c3526-c319-4f26-8cde-747c95011af7",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:10:55.134Z",
   "updateDate": "2025-09-16T12:11:24.736Z",
   "_propHash": "4d427fe22477cef84ea78b166130269a",
   "_docHash": "b9c75ab0e3f6c40fa0fd23a3de673e32",
   "hash": "6v8F2e4bLdf6yccg4XVh5BFHsDEm41aC36FnnofEWf3W",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "project",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_assign",
   "schema": "#6482c99e-4af8-4cd1-94e6-ee82d2284197&1.0.0",
   "option": {
     "status": "Waiting to Validate"
   },
   "relationships": [
     "1758024619.744335000",
     "1758024539.869960000"
   ],
   "owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
   "assignedTo": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
   "group": "5d49111f-c662-4494-ac71-35c4826f5684",
   "accounts": {
     "default": "0.0.6856932"
   },
   "tokens": null,
   "topicId": "0.0.6856972",
   "messageId": "1758024652.684467000",
   "messageHash": "CQ4LpNhuNA9MGv5HdmaAdLz3oT42wbTsxUE7VNzzEGSL",
   "messageIds": [
     "1758024652.684467000"
   ],
   "document": {
     "id": "urn:uuid:0ee4a666-7b8a-4857-afcc-b048aec177dc",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
     "issuanceDate": "2025-09-16T12:10:29.158Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject": *there is huge payload*,
     "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:10:32Z",
       "verificationMethod": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..-czwVoPGwWiLFbo0xjcAgf9buHVqUdD59HKIJFZa-XbYk_2uSDaskCvQxpDrHlCJrwSe0BL76Gpb6UpQ-G9TCw"
     }
   },
   "documentFileId": "68c953ec7d1632a3d92d6408",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c953cf7d1632a3d92d63dd",
   "__sourceTag__": "project_grid_vvb_projects",
   "history": [
     {
       "labelValue": "Waiting to be Added",
       "created": "2025-09-16T12:10:55.533Z"
     },
     {
       "labelValue": "Waiting to Validate",
       "created": "2025-09-16T12:11:19.704Z"
     },
     {
       "labelValue": "Waiting to Validate",
       "created": "2025-09-16T12:11:24.918Z"
     }
   ],
   "id": "68c953cf7d1632a3d92d63dd"
 }
],
"blocks": [
 {
   "id": "3e7de6b5-5d05-4908-863a-c69a5e67aaf7",
   "uiMetaData": {
     "options": [],
     "content": "Project Name"
   },
   "blockType": "filtersAddon"
 }
],
"commonAddons": [
 {
   "id": "620fb126-e25e-42c1-b0ba-96d90714c49d",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "89d4600d-7289-416b-b022-59a6d6fe436f",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "df25c1dd-bfa2-45e7-a101-ccd3870211eb",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "70d6e612-6f8b-44b9-8405-6a7b9280c583",
   "blockType": "historyAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.project_details.G5",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Operation",
   "name": "option.status",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "approve_project_btn",
   "width": "250px",
   "bindGroup": "project_grid_vvb_projects"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link"
 },
 {
   "title": "Operation",
   "name": "option.status",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_project_vvb_btn",
   "bindGroup": "project_grid_vvb_projects_approved",
   "width": "250px"
 },
 {
   "title": "Operation",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": "250px"
 },
 {
   "title": "Validation Report",
   "name": "validation_report",
   "tooltip": "",
   "type": "block",
   "bindGroup": "project_grid_vvb_projects_approved",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "add_new_validation_report",
   "bindBlocks": [],
   "width": "250px",
   "content": "Add Validation Report"
 }
],
"viewHistory": true
}
```

**Send the updated payload in the request:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/approve_project_btn/blocks`

With body:

```json5
*changed project data*
```

### 6 Report Flow

#### 6.1 Login by PP

#### 6.2 Create Report

<figure><img src="/files/7LrelM7G6l2ObtnXAfmI" alt=""><figcaption></figcaption></figure>

**Wait until the project status changes to “approved\_project”:**

<mark style="color:red;">`GET`</mark> `"http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/project_grid_pp_2/blocks"`

Save the response data as a reference:

```json5
{
"id": "599bc800-3413-4606-b770-563fcfdef5fb",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:10:55.134Z",
   "updateDate": "2025-09-16T12:11:29.995Z",
   "_propHash": "1144c08caccff063c2b48dab21b4799d",
   "_docHash": "b9c75ab0e3f6c40fa0fd23a3de673e32",
   "hash": "6v8F2e4bLdf6yccg4XVh5BFHsDEm41aC36FnnofEWf3W",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "project",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "approved_project_status",
   "schema": "#6482c99e-4af8-4cd1-94e6-ee82d2284197&1.0.0",
   "option": {
     "status": "Validated"
   },
   "relationships": [
     "1758024619.744335000",
     "1758024539.869960000"
   ],
   "owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
   "assignedTo": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
   "group": "5d49111f-c662-4494-ac71-35c4826f5684",
   "accounts": {
     "default": "0.0.6856932"
   },
   "tokens": null,
   "topicId": "0.0.6856972",
   "messageId": "1758024652.684467000",
   "messageHash": "CQ4LpNhuNA9MGv5HdmaAdLz3oT42wbTsxUE7VNzzEGSL",
   "messageIds": [
     "1758024652.684467000"
   ],
   "document": {
     "id": "urn:uuid:0ee4a666-7b8a-4857-afcc-b048aec177dc",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
     "issuanceDate": "2025-09-16T12:10:29.158Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject": *there are huge payload*,
     "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:10:32Z",
       "verificationMethod": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..-czwVoPGwWiLFbo0xjcAgf9buHVqUdD59HKIJFZa-XbYk_2uSDaskCvQxpDrHlCJrwSe0BL76Gpb6UpQ-G9TCw"
     }
   },
   "documentFileId": "68c953f27d1632a3d92d6411",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c953cf7d1632a3d92d63dd",
   "__sourceTag__": "project_grid_pp_2_validated_projects_own",
   "history": [
     {
       "labelValue": "Waiting to be Added",
       "created": "2025-09-16T12:10:55.533Z"
     },
     {
       "labelValue": "Waiting to Validate",
       "created": "2025-09-16T12:11:19.704Z"
     },
     {
       "labelValue": "Waiting to Validate",
       "created": "2025-09-16T12:11:24.918Z"
     },
     {
       "labelValue": "Validated",
       "created": "2025-09-16T12:11:30.166Z"
     }
   ],
   "id": "68c953cf7d1632a3d92d63dd"
 }
],
"blocks": [
 {
   "id": "5e1b4ecb-5860-4a53-a734-de96bbf45fe3",
   "uiMetaData": {
     "options": [],
     "title": "",
     "content": "Project Name"
   },
   "blockType": "filtersAddon"
 }
],
"commonAddons": [
 {
   "id": "1bec12bf-486d-4014-994a-ee0937a64ae9",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "1c88d5df-6519-496f-b02f-76de9ce3b0be",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "c1cd6720-6129-4c62-ae8f-4b850bb113b7",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "ad0aa831-b318-4e93-b6fa-eb01fef01f83",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "930d5a57-080e-4289-9fe7-3f71192e200f",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "f41365cf-a1c5-4394-bfda-a0d74e7f9bb1",
   "blockType": "historyAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.project_details.G5",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Status",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": "170px"
 },
 {
   "title": "Assign",
   "name": "assignedTo",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "assign_vvb",
   "bindGroup": "project_grid_pp_2_waiting_to_validate_projects",
   "width": "150px"
 },
 {
   "title": "Assign",
   "name": "assignedTo",
   "tooltip": "",
   "type": "text",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "",
   "bindGroup": "project_grid_pp_2_validated_projects",
   "width": "150px"
 },
 {
   "title": "Add Report",
   "name": "report",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "add_report_bnt",
   "bindGroup": "project_grid_pp_2_validated_projects",
   "width": "150px"
 },
 {
   "title": "View Reports",
   "name": "document.credentialSubject.0.id",
   "tooltip": "",
   "type": "button",
   "action": "link",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "report_grid_pp",
   "content": "View Reports",
   "bindGroup": "project_grid_pp_2_validated_projects",
   "width": "150px"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_project_pp_btn",
   "width": "100px",
   "bindGroup": "project_grid_pp_2_waiting_to_add_projects"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_project_pp_btn",
   "width": "100px",
   "bindGroup": "project_grid_pp_2_waiting_to_validate_projects"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_project_pp_btn",
   "width": "100px",
   "bindGroup": "project_grid_pp_2_validated_projects_own"
 }
],
"viewHistory": true
}
```

**Send a request with the reference:**

<mark style="color:green;">`POST`</mark> `"http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/add_report_bnt/blocks"`

```json5
body: {
   "document": *payload from file*,
   "ref": *changed reference from previous request*
}
```

Successful response looks like:

```json5
{
"policyId": "68c952870fd12e530dddadf8",
"tag": "add_report_bnt",
"hash": "GGJ47euPmaetz9rmHMNbVdmmpPPA43ynV1vn1Mast55v",
"document": {
 "id": "urn:uuid:78d8dbbc-1082-4bfb-8129-98bc953ad735",
 "type": [
   "VerifiableCredential"
 ],
 "issuer": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
 "issuanceDate": "2025-09-16T12:12:06.291Z",
 "@context": [
   "https://www.w3.org/2018/credentials/v1",
   "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
 ],
 "credentialSubject":*there is huge payload*,
 "proof": {
   "type": "Ed25519Signature2018",
   "created": "2025-09-16T12:12:09Z",
   "verificationMethod": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936#did-root-key",
   "proofPurpose": "assertionMethod",
   "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..1b0SqKVYONgYnwmGpqGBnHHYKjt4GuiqNMRbM3El8TLM4Gu95wKx47c-Vy3Crc2kLb9a-c_n6UJXNBvh1ZFtDA"
 }
},
"owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
"group": "5d49111f-c662-4494-ac71-35c4826f5684",
"hederaStatus": "NEW",
"signature": 0,
"type": "#81ac56ff-885d-4764-95be-10f392b4d16b&1.0.0",
"schema": "#81ac56ff-885d-4764-95be-10f392b4d16b&1.0.0",
"accounts": {
 "default": "0.0.6856932"
},
"relationships": [
 "1758024717.023047000"
]
}
```

**Wait until the project status changes to “Waiting for Verification”:**

<figure><img src="/files/R8Ok5XCyVZJUOKXnjVA2" alt=""><figcaption></figcaption></figure>

<mark style="color:red;">`GET`</mark> `"http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/report_grid_pp/blocks"`

```json5
{
"id": "a9734879-66a6-489e-937a-8d5f60342904",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:13:05.022Z",
   "updateDate": "2025-09-16T12:13:05.160Z",
   "_propHash": "b5d154a97533da19fbbf8b572b0187ca",
   "_docHash": "1b110e74d889418715c34034e2d9e9cd",
   "hash": "CNV8rRV5pUTBRn8zGMDqKsMwyGs5PVkz799HMS8Q5CwA",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "report",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_report",
   "schema": "#81ac56ff-885d-4764-95be-10f392b4d16b&1.0.0",
   "option": {
     "status": "Waiting for Verification"
   },
   "relationships": [
     "1758024750.620775315",
     "1758024539.869960000"
   ],
   "owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
   "group": "5d49111f-c662-4494-ac71-35c4826f5684",
   "accounts": {
     "default": "0.0.6856932"
   },
   "tokens": null,
   "topicId": "0.0.6856972",
   "messageId": "1758024781.504726000",
   "messageHash": "3hygSHh7DwSQqD22k7dqVHF6j6vfPHD8rJVz27APYs8g",
   "messageIds": [
     "1758024781.504726000"
   ],
   "document": {
     "id": "urn:uuid:04fb8436-43f5-4fa3-bbfb-15197cb1301b",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
     "issuanceDate": "2025-09-16T12:12:39.393Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject": *there are huge payload*,
     "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:12:42Z",
       "verificationMethod": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..bsuQWFYWZi1xusjf3pK2GOBNDvA1NbKBpcBsxij2UCQHcDVmZCTGTLJuSdECpyb_bl0i9D-Vv9quYFD-4RtVDA"
     }
   },
   "documentFileId": "68c954517d1632a3d92d644e",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c954507d1632a3d92d6446",
   "__sourceTag__": "report_grid_pp_reports",
   "history": [
     {
       "labelValue": "Waiting for Verification",
       "created": "2025-09-16T12:13:05.316Z"
     }
   ],
   "id": "68c954507d1632a3d92d6446"
 }
],
"blocks": [
 {
   "id": "e0d9441c-9a20-4cc5-948b-567750f2e85c",
   "uiMetaData": {
     "options": [],
     "content": "Project Name"
   },
   "blockType": "filtersAddon"
 }
],
"commonAddons": [
 {
   "id": "92aaa2d9-368d-4e03-ad92-c445480fbfcb",
   "uiMetaData": {
     "type": "blank",
     "options": []
   },
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "064e1967-e94e-48b0-9f47-c6c270ee731b",
   "uiMetaData": {
     "type": "blank",
     "options": []
   },
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "2eac0a02-0146-4cb9-a3a3-a88df5f991a8",
   "blockType": "historyAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.project_details.G5",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Status",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": "175px"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link"
 },
 {
   "title": "Revoke",
   "name": "Revoke",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_report_pp_btn",
   "width": "100px",
   "bindGroup": "report_grid_pp_reports"
 },
 {
   "title": "Assign",
   "name": "assignedTo",
   "tooltip": "",
   "type": "block",
   "bindGroup": "report_grid_pp_reports",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "assign_vvb_mr",
   "bindBlocks": [],
   "width": "150px"
 },
 {
   "title": "Assign",
   "name": "assignedTo",
   "tooltip": "",
   "type": "text",
   "bindGroup": "report_grid_pp_reports",
   "width": "150px"
 }
],
"viewHistory": true
}
```

#### 6.3 Login by PP

#### 6.4 Assign Report

<figure><img src="/files/wkDOye6lHkp5rRKO8ea8" alt=""><figcaption></figcaption></figure>

**Get the report reference by saving the response data:**

<mark style="color:red;">`GET`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/report_grid_pp/blocks`

Create and fill the field with the VVB DID:

```json5
{
"id": "a9734879-66a6-489e-937a-8d5f60342904",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:13:05.022Z",
   "updateDate": "2025-09-16T12:13:05.160Z",
   "_propHash": "b5d154a97533da19fbbf8b572b0187ca",
   "_docHash": "1b110e74d889418715c34034e2d9e9cd",
   "hash": "CNV8rRV5pUTBRn8zGMDqKsMwyGs5PVkz799HMS8Q5CwA",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "report",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_report",
   "schema": "#81ac56ff-885d-4764-95be-10f392b4d16b&1.0.0",
   "option": {
     "status": "Waiting for Verification"
   },
   "relationships": [
     "1758024750.620775315",
     "1758024539.869960000"
   ],
   "owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
   "group": "5d49111f-c662-4494-ac71-35c4826f5684",
   "accounts": {
     "default": "0.0.6856932"
   },
   "tokens": null,
   "topicId": "0.0.6856972",
   "messageId": "1758024781.504726000",
   "messageHash": "3hygSHh7DwSQqD22k7dqVHF6j6vfPHD8rJVz27APYs8g",
   "messageIds": [
     "1758024781.504726000"
   ],
   "document": {
     "id": "urn:uuid:04fb8436-43f5-4fa3-bbfb-15197cb1301b",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
     "issuanceDate": "2025-09-16T12:12:39.393Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject": *there is huge payload*,
     "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:12:42Z",
       "verificationMethod": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..bsuQWFYWZi1xusjf3pK2GOBNDvA1NbKBpcBsxij2UCQHcDVmZCTGTLJuSdECpyb_bl0i9D-Vv9quYFD-4RtVDA"
     }
   },
   "documentFileId": "68c954517d1632a3d92d644e",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c954507d1632a3d92d6446",
   "__sourceTag__": "report_grid_pp_reports",
   "history": [
     {
       "labelValue": "Waiting for Verification",
       "created": "2025-09-16T12:13:05.316Z"
     }
   ],
   "id": "68c954507d1632a3d92d6446"
 }
],
"blocks": [
 {
   "id": "e0d9441c-9a20-4cc5-948b-567750f2e85c",
   "uiMetaData": {
     "options": [],
     "content": "Project Name"
   },
   "blockType": "filtersAddon"
 }
],
"commonAddons": [
 {
   "id": "92aaa2d9-368d-4e03-ad92-c445480fbfcb",
   "uiMetaData": {
     "type": "blank",
     "options": []
   },
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "064e1967-e94e-48b0-9f47-c6c270ee731b",
   "uiMetaData": {
     "type": "blank",
     "options": []
   },
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "2eac0a02-0146-4cb9-a3a3-a88df5f991a8",
   "blockType": "historyAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.project_details.G5",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Status",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": "175px"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link"
 },
 {
   "title": "Revoke",
   "name": "Revoke",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_report_pp_btn",
   "width": "100px",
   "bindGroup": "report_grid_pp_reports"
 },
 {
   "title": "Assign",
   "name": "assignedTo",
   "tooltip": "",
   "type": "block",
   "bindGroup": "report_grid_pp_reports",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "assign_vvb_mr",
   "bindBlocks": [],
   "width": "150px"
 },
 {
   "title": "Assign",
   "name": "assignedTo",
   "tooltip": "",
   "type": "text",
   "bindGroup": "report_grid_pp_reports",
   "width": "150px"
 }
],
"viewHistory": true
}
```

**Send the updated report data in the request:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/assign_vvb_mr/blocks`

With body:

```json5
*changed project data*
```

#### 6.5 Login by VVB

#### 6.6 Approve Report

<figure><img src="/files/5ww1AX4bwXWATehb8ipc" alt=""><figcaption></figcaption></figure>

**Wait until the report status changes to “Waiting for Verification”:**

<mark style="color:red;">`GET`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/report_grid_vvb/blocks`

<figure><img src="/files/CYsOLrkPIfvbnXsXrVVh" alt=""><figcaption></figcaption></figure>

Save the response data as a reference and update the status to “Verified”:

```json5
{
"id": "4f75cbc4-a5a3-4552-b45b-d582c0f4a613",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:13:05.022Z",
   "updateDate": "2025-09-16T12:13:09.280Z",
   "_propHash": "d8936ab43b2350f19dcaf70f95b4b0e1",
   "_docHash": "1b110e74d889418715c34034e2d9e9cd",
   "hash": "CNV8rRV5pUTBRn8zGMDqKsMwyGs5PVkz799HMS8Q5CwA",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "report",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_mr_assign",
   "schema": "#81ac56ff-885d-4764-95be-10f392b4d16b&1.0.0",
   "option": {
     "status": "Waiting for Verification"
   },
   "relationships": [
     "1758024750.620775315",
     "1758024539.869960000"
   ],
   "owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
   "assignedTo": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
   "group": "5d49111f-c662-4494-ac71-35c4826f5684",
   "accounts": {
     "default": "0.0.6856932"
   },
   "tokens": null,
   "topicId": "0.0.6856972",
   "messageId": "1758024781.504726000",
   "messageHash": "3hygSHh7DwSQqD22k7dqVHF6j6vfPHD8rJVz27APYs8g",
   "messageIds": [
     "1758024781.504726000"
   ],
   "document": {
     "id": "urn:uuid:04fb8436-43f5-4fa3-bbfb-15197cb1301b",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
     "issuanceDate": "2025-09-16T12:12:39.393Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject": *there is huge payload*,
     "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:12:42Z",
       "verificationMethod": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..bsuQWFYWZi1xusjf3pK2GOBNDvA1NbKBpcBsxij2UCQHcDVmZCTGTLJuSdECpyb_bl0i9D-Vv9quYFD-4RtVDA"
     }
   },
   "documentFileId": "68c954557d1632a3d92d6457",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c954507d1632a3d92d6446",
   "__sourceTag__": "report_grid_vvb_reports",
   "history": [
     {
       "labelValue": "Waiting for Verification",
       "created": "2025-09-16T12:13:05.316Z"
     },
     {
       "labelValue": "Waiting for Verification",
       "created": "2025-09-16T12:13:09.461Z"
     }
   ],
   "id": "68c954507d1632a3d92d6446"
 }
],
"blocks": [
 {
   "id": "a0b880db-55f7-43c0-9123-865683be36ed",
   "uiMetaData": {
     "options": [],
     "content": "Project Name"
   },
   "blockType": "filtersAddon"
 }
],
"commonAddons": [
 {
   "id": "67ccfed1-7f3f-4706-a6cd-be6e3bebe22b",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "c6a56098-64d4-472e-90bc-de4a64530ea7",
   "uiMetaData": {
     "type": "blank"
   },
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "07b64d9a-8ba7-4f0d-ac6e-ce81fdeaa21d",
   "uiMetaData": {
     "type": "blank"
   },
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "1e51fa88-7bd1-42c1-b67e-a412cdd05bce",
   "blockType": "historyAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.project_details.G5",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Status",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": ""
 },
 {
   "title": "Operation",
   "name": "option.status",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "approve_report_btn",
   "bindGroup": "report_grid_vvb_reports",
   "width": "150px"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link",
   "width": "170px"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "width": "100px",
   "bindGroup": "report_grid_vvb_reports(approved)",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_reassign_report_btn"
 },
 {
   "title": "Verification Report",
   "name": "verification_report",
   "tooltip": "",
   "type": "block",
   "bindGroup": "report_grid_vvb_reports(approved)",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "add_verification_report",
   "bindBlocks": [],
   "content": "Add Verification Report",
   "width": "250px"
 }
],
"viewHistory": true
}
```

**Send the updated payload in the request:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/approve_report_btn/blocks`

With body:

```json5
{
   "document": *changed project data*,
   "tag": "Button_0"
}
```

**Wait until the project status is “Verified”:**

<mark style="color:red;">`GET`</mark> `"http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/report_grid_vvb/blocks"`

```json5
{
"id": "4f75cbc4-a5a3-4552-b45b-d582c0f4a613",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:13:45.538Z",
   "updateDate": "2025-09-16T12:13:45.735Z",
   "_propHash": "a6844b98f3581509f6c28490767085f8",
   "_docHash": "48f1da1697c4e224c071493659ff0042",
   "hash": "BRenHy1UbB8JgA7nGtV8qxGP7bKPCj2smHrCyeJSz9Te",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "approved_report",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_reassign_report",
   "schema": "#81ac56ff-885d-4764-95be-10f392b4d16b&1.0.0",
   "option": {
     "status": "Verified"
   },
   "relationships": [
     "1758024781.504726000"
   ],
   "owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
   "assignedTo": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
   "group": "5d49111f-c662-4494-ac71-35c4826f5684",
   "accounts": {
     "default": "0.0.6856932"
   },
   "topicId": "0.0.6856972",
   "messageId": "1758024822.724992000",
   "messageHash": "14Xx4TD1GpN9NULGZ1cF16xcLuMq1CueqXbR3uAovq5d",
   "messageIds": [
     "1758024822.724992000"
   ],
   "document": {
     "id": "urn:uuid:f81fcb76-3e03-4cc2-9efc-e036a50f184b",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
     "issuanceDate": "2025-09-16T12:13:14.673Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject":  *there are huge payload*,
     "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:13:17Z",
       "verificationMethod": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..O1tAnUlwYRU7ohgt9lvdnVyzKWseVMphSmS3Y1_9Cp_MoU7hsX84O9JVD14HbdC6Lp538wi2EuNzbVXPEC4jCg"
     }
   },
   "documentFileId": "68c954797d1632a3d92d6472",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c954797d1632a3d92d646a",
   "__sourceTag__": "report_grid_vvb_reports(approved)",
   "history": [
     {
       "labelValue": "Verified",
       "created": "2025-09-16T12:13:45.931Z"
     }
   ],
   "id": "68c954797d1632a3d92d646a"
 }
],
"blocks": [
 {
   "id": "a0b880db-55f7-43c0-9123-865683be36ed",
   "uiMetaData": {
     "options": [],
     "content": "Project Name"
   },
   "blockType": "filtersAddon"
 }
],
"commonAddons": [
 {
   "id": "67ccfed1-7f3f-4706-a6cd-be6e3bebe22b",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "c6a56098-64d4-472e-90bc-de4a64530ea7",
   "uiMetaData": {
     "type": "blank"
   },
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "07b64d9a-8ba7-4f0d-ac6e-ce81fdeaa21d",
   "uiMetaData": {
     "type": "blank"
   },
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "1e51fa88-7bd1-42c1-b67e-a412cdd05bce",
   "blockType": "historyAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.project_details.G5",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Status",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": ""
 },
 {
   "title": "Operation",
   "name": "option.status",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "approve_report_btn",
   "bindGroup": "report_grid_vvb_reports",
   "width": "150px"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link",
   "width": "170px"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "width": "100px",
   "bindGroup": "report_grid_vvb_reports(approved)",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_reassign_report_btn"
 },
 {
   "title": "Verification Report",
   "name": "verification_report",
   "tooltip": "",
   "type": "block",
   "bindGroup": "report_grid_vvb_reports(approved)",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "add_verification_report",
   "bindBlocks": [],
   "content": "Add Verification Report",
   "width": "250px"
 }
],
"viewHistory": true
}
```

#### 6.7 Create Validation Report

<figure><img src="/files/LWVs02rSz3O6qi9GRkVi" alt=""><figcaption></figcaption></figure>

**Get the reference for creating the report:**

<mark style="color:red;">`GET`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/project_grid_vvb/blocks`

Save the response data as a reference and update the status to “Verified”:

```json5
{
"id": "302c3526-c319-4f26-8cde-747c95011af7",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:12:00.834Z",
   "updateDate": "2025-09-16T12:12:01.009Z",
   "_propHash": "2617698a9caff732a76322d13b7ac56e",
   "_docHash": "337bbdf96aeb94d10c8a3bc372dedc93",
   "hash": "BUgiqBerAEzu2JVx2TyyDa9fCA6edpJ8b8U7cp6KiSa7",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "approved_project",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_reassign_project",
   "schema": "#6482c99e-4af8-4cd1-94e6-ee82d2284197&1.0.0",
   "option": {
     "status": "Validated"
   },
   "relationships": [
     "1758024652.684467000",
     "1758024674.704312000"
   ],
   "owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
   "assignedTo": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
   "group": "5d49111f-c662-4494-ac71-35c4826f5684",
   "accounts": {
     "default": "0.0.6856932"
   },
   "topicId": "0.0.6856972",
   "messageId": "1758024717.023047000",
   "messageHash": "8JqbHxt1UqoYvH5feQePf6TZPq666XuFpRpTrmttGCWr",
   "messageIds": [
     "1758024717.023047000"
   ],
   "document": {
     "id": "urn:uuid:35a62c65-eb23-4cdf-bdd2-6563f09db110",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
     "issuanceDate": "2025-09-16T12:11:30.443Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject": *there is huge payload*,
     "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:11:33Z",
       "verificationMethod": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..P-5j3LiJY3T2b5X1hcc7i3RkZmC_cfCeDZKyGwrX7Tqe5Yc6_buXwr-eLfLchAguAfnrBPPkbj9d2RtH2khTCw"
     }
   },
   "documentFileId": "68c954117d1632a3d92d6423",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c954107d1632a3d92d641b",
   "__sourceTag__": "project_grid_vvb_projects_approved",
   "history": [
     {
       "labelValue": "Validated",
       "created": "2025-09-16T12:12:01.192Z"
     }
   ],
   "id": "68c954107d1632a3d92d641b"
 }
],
"blocks": [
 {
   "id": "3e7de6b5-5d05-4908-863a-c69a5e67aaf7",
   "uiMetaData": {
     "options": [],
     "content": "Project Name"
   },
   "blockType": "filtersAddon"
 }
],
"commonAddons": [
 {
   "id": "620fb126-e25e-42c1-b0ba-96d90714c49d",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "89d4600d-7289-416b-b022-59a6d6fe436f",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "df25c1dd-bfa2-45e7-a101-ccd3870211eb",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "70d6e612-6f8b-44b9-8405-6a7b9280c583",
   "blockType": "historyAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.project_details.G5",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Operation",
   "name": "option.status",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "approve_project_btn",
   "width": "250px",
   "bindGroup": "project_grid_vvb_projects"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link"
 },
 {
   "title": "Operation",
   "name": "option.status",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_project_vvb_btn",
   "bindGroup": "project_grid_vvb_projects_approved",
   "width": "250px"
 },
 {
   "title": "Operation",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": "250px"
 },
 {
   "title": "Validation Report",
   "name": "validation_report",
   "tooltip": "",
   "type": "block",
   "bindGroup": "project_grid_vvb_projects_approved",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "add_new_validation_report",
   "bindBlocks": [],
   "width": "250px",
   "content": "Add Validation Report"
 }
],
"viewHistory": true
}
```

**Send the request with the updated payload. (The payload for the validation report will be attached separately.):**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/add_new_validation_report/blocks`

With body:

```json5
{
   "document": *validation report payload from file*,
   "ref": *changed report data*
}
```

Successful response looks like:

```json5
{
  "policyId": "68c952870fd12e530dddadf8",
  "tag": "add_new_validation_report",
  "hash": "6pUjW1QtxbfEz4L7wHvNU9UhQn8wsZAfiVHkBgJEnrzk",
  "document": {
    "id": "urn:uuid:8ca71bb7-0d79-40b5-8ea1-9817f0ceb885",
    "type": [
      "VerifiableCredential"
    ],
    "issuer": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
    "issuanceDate": "2025-09-16T12:13:49.250Z",
    "@context": [
      "https://www.w3.org/2018/credentials/v1",
      "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
    ],
    "credentialSubject": *there is payload from file*
    "proof": {
      "type": "Ed25519Signature2018",
      "created": "2025-09-16T12:13:52Z",
      "verificationMethod": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936#did-root-key",
      "proofPurpose": "assertionMethod",
      "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..fRswed3BAD9N2r_-eNAalvUZ7A-PlMlHJ0bMAH7EU_qMUEpX_k5xS82CsmEuH6H0df29bpUbUKB3VPL-0QeKDQ"
    }
  },
  "owner": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
  "group": "2c6c93e9-d089-4518-9f66-e548df9e0cac",
  "hederaStatus": "NEW",
  "signature": 0,
  "type": "#163325db-0a46-4199-8628-5ed95d671622&1.0.0",
  "schema": "#163325db-0a46-4199-8628-5ed95d671622&1.0.0",
  "accounts": {
    "default": "0.0.6856934"
  },
  "relationships": [
    "1758024717.023047000"
  ]
}
```

#### 6.8 Login by SR

#### 6.9 Approve Validation Report

<figure><img src="/files/a5Pjobq2fY8paGsDqNmQ" alt=""><figcaption></figcaption></figure>

**Wait until the validation report status changes to “Submitted”:**

<mark style="color:red;">`GET`</mark> `"http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/validation_reports_verra/blocks"`

Save the response data as a reference and update the status to “APPROVED”:

```json5
{
"id": "5d76bfa6-38d2-461c-90ef-0d3bdd1b6477",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:14:08.848Z",
   "updateDate": "2025-09-16T12:14:08.865Z",
   "_propHash": "720b202a9eea13d72d1824ae17aa4363",
   "_docHash": "4d4387e2d9ab267a77a7c3e4c2d532bd",
   "hash": "6pUjW1QtxbfEz4L7wHvNU9UhQn8wsZAfiVHkBgJEnrzk",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "validation_report",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_validation_report_db",
   "schema": "#163325db-0a46-4199-8628-5ed95d671622&1.0.0",
   "option": {
     "status": "Submitted"
   },
   "relationships": [
     "1758024717.023047000",
     "1758024558.020152392"
   ],
   "owner": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
   "group": "2c6c93e9-d089-4518-9f66-e548df9e0cac",
   "accounts": {
     "default": "0.0.6856934"
   },
   "topicId": "0.0.6856972",
   "messageId": "1758024845.830259699",
   "messageHash": "6GM36MfsfmfuGdqK1VUQLFwS2hkuxko4ouMJfjN8wi25",
   "messageIds": [
     "1758024845.830259699"
   ],
   "document": {
     "id": "urn:uuid:8ca71bb7-0d79-40b5-8ea1-9817f0ceb885",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
     "issuanceDate": "2025-09-16T12:13:49.250Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject": *there are huge payload*,
             "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:13:52Z",
       "verificationMethod": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..fRswed3BAD9N2r_-eNAalvUZ7A-PlMlHJ0bMAH7EU_qMUEpX_k5xS82CsmEuH6H0df29bpUbUKB3VPL-0QeKDQ"
     }
   },
   "documentFileId": "68c954907d1632a3d92d6483",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c954907d1632a3d92d6480",
   "__sourceTag__": "validation_reports_verra_all_reports",
   "id": "68c954907d1632a3d92d6480"
 }
],
"blocks": [],
"commonAddons": [
 {
   "id": "87ad15bf-06ce-44fc-9068-84efb4f40d19",
   "blockType": "documentsSourceAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.ref",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link"
 },
 {
   "title": "Status",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": "250px"
 },
 {
   "title": "Operation",
   "name": "operation",
   "tooltip": "",
   "type": "block",
   "bindGroup": "validation_reports_verra_all_reports",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "approve_validation_report_btn",
   "bindBlocks": [],
   "width": "150px"
 }
],
"title": "Validation Reports",
"viewHistory": false
}
```

**Send the updated payload in the request:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/approve_validation_report_btn/blocks`

With body:

```json5
{
   "document": *changed report data*,
   "tag": "Approve_Button_Validation"
}
```

#### 6.10 Login by VVB

#### 6.11 Create Verification Report

<figure><img src="/files/36SGbb6jAKwYZqorLoyX" alt=""><figcaption></figcaption></figure>

**Get the reference for creating the report:**

<mark style="color:red;">`GET`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/report_grid_vvb/blocks`

Save the response data as a reference and update the status to “Verified”:

```json5
{
"id": "4f75cbc4-a5a3-4552-b45b-d582c0f4a613",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:13:45.538Z",
   "updateDate": "2025-09-16T12:13:45.735Z",
   "_propHash": "a6844b98f3581509f6c28490767085f8",
   "_docHash": "48f1da1697c4e224c071493659ff0042",
   "hash": "BRenHy1UbB8JgA7nGtV8qxGP7bKPCj2smHrCyeJSz9Te",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "approved_report",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_reassign_report",
   "schema": "#81ac56ff-885d-4764-95be-10f392b4d16b&1.0.0",
   "option": {
     "status": "Verified"
   },
   "relationships": [
     "1758024781.504726000"
   ],
   "owner": "did:hedera:testnet:GJRcdMgwGUfosDKL1o3qFxLTTFAGWTw4JU8tFArMcdaH_0.0.6855936",
   "assignedTo": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
   "group": "5d49111f-c662-4494-ac71-35c4826f5684",
   "accounts": {
     "default": "0.0.6856932"
   },
   "topicId": "0.0.6856972",
   "messageId": "1758024822.724992000",
   "messageHash": "14Xx4TD1GpN9NULGZ1cF16xcLuMq1CueqXbR3uAovq5d",
   "messageIds": [
     "1758024822.724992000"
   ],
   "document": {
     "id": "urn:uuid:f81fcb76-3e03-4cc2-9efc-e036a50f184b",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
     "issuanceDate": "2025-09-16T12:13:14.673Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject": *there is huge payload*,
     "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:13:17Z",
       "verificationMethod": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..O1tAnUlwYRU7ohgt9lvdnVyzKWseVMphSmS3Y1_9Cp_MoU7hsX84O9JVD14HbdC6Lp538wi2EuNzbVXPEC4jCg"
     }
   },
   "documentFileId": "68c954797d1632a3d92d6472",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c954797d1632a3d92d646a",
   "__sourceTag__": "report_grid_vvb_reports(approved)",
   "history": [
     {
       "labelValue": "Verified",
       "created": "2025-09-16T12:13:45.931Z"
     }
   ],
   "id": "68c954797d1632a3d92d646a"
 }
],
"blocks": [
 {
   "id": "a0b880db-55f7-43c0-9123-865683be36ed",
   "uiMetaData": {
     "options": [],
     "content": "Project Name"
   },
   "blockType": "filtersAddon"
 }
],
"commonAddons": [
 {
   "id": "67ccfed1-7f3f-4706-a6cd-be6e3bebe22b",
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "c6a56098-64d4-472e-90bc-de4a64530ea7",
   "uiMetaData": {
     "type": "blank"
   },
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "07b64d9a-8ba7-4f0d-ac6e-ce81fdeaa21d",
   "uiMetaData": {
     "type": "blank"
   },
   "blockType": "documentsSourceAddon"
 },
 {
   "id": "1e51fa88-7bd1-42c1-b67e-a412cdd05bce",
   "blockType": "historyAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.project_details.G5",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Status",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": ""
 },
 {
   "title": "Operation",
   "name": "option.status",
   "tooltip": "",
   "type": "block",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "approve_report_btn",
   "bindGroup": "report_grid_vvb_reports",
   "width": "150px"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link",
   "width": "170px"
 },
 {
   "title": "Revoke",
   "name": "",
   "tooltip": "",
   "type": "block",
   "width": "100px",
   "bindGroup": "report_grid_vvb_reports(approved)",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "revoke_reassign_report_btn"
 },
 {
   "title": "Verification Report",
   "name": "verification_report",
   "tooltip": "",
   "type": "block",
   "bindGroup": "report_grid_vvb_reports(approved)",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "add_verification_report",
   "bindBlocks": [],
   "content": "Add Verification Report",
   "width": "250px"
 }
],
"viewHistory": true
}
```

**Send the request with the updated payload. (The payload for the validation report will be attached separately.):**

<mark style="color:green;">`POST`</mark>` `` ``http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/add_verification_report/blocks `

With body:

```json5
{
   "document": *verification report payload from file*,
   "ref": *changed report data*
}
```

Successful response looks like:

```json5
{
  "policyId": "68c952870fd12e530dddadf8",
  "tag": "add_verification_report",
  "hash": "DwXaU994DhLgo36wXPcoHg2YdzXVrwYmWEgg44Xv7zKW",
  "document": {
    "id": "urn:uuid:23c30e34-2e79-46a2-b1bd-150199a53b4a",
    "type": [
      "VerifiableCredential"
    ],
    "issuer": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
    "issuanceDate": "2025-09-16T12:14:13.166Z",
    "@context": [
      "https://www.w3.org/2018/credentials/v1",
      "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
    ],
    "credentialSubject": *there is payload from file*
    "proof": {
      "type": "Ed25519Signature2018",
      "created": "2025-09-16T12:14:15Z",
      "verificationMethod": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936#did-root-key",
      "proofPurpose": "assertionMethod",
      "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..PJ8V3NOGKrJ3btTmbES9iLPv15DLD-hjQulq-6CVFBPc6597Mhbufd97r7ZqHIA3XOA2xmWMfFLcgmXxzM8fDg"
    }
  },
  "owner": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
  "group": "2c6c93e9-d089-4518-9f66-e548df9e0cac",
  "hederaStatus": "NEW",
  "signature": 0,
  "type": "#2321fb67-54e0-464d-bcd5-8dc2dbad2c41&1.0.0",
  "schema": "#2321fb67-54e0-464d-bcd5-8dc2dbad2c41&1.0.0",
  "accounts": {
    "default": "0.0.6856934"
  },
  "relationships": [
    "1758024822.724992000"
  ]
}
```

#### 6.12 Login by SR

#### 6.13 Approve Verification Report

<figure><img src="/files/RHk8rlFj0HkDbHuTK2NT" alt=""><figcaption></figcaption></figure>

**Wait until the verification report status changes to “Submitted”:**

<mark style="color:red;">`GET`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/verification_reports_verra/blocks`

Save the response data as a reference and update the status to “APPROVED”:

```json5
{
"id": "ae478634-a214-4909-b1c2-b56bf7876626",
"blockType": "interfaceDocumentsSourceBlock",
"actionType": "local",
"readonly": false,
"data": [
 {
   "createDate": "2025-09-16T12:14:34.270Z",
   "updateDate": "2025-09-16T12:14:34.289Z",
   "_propHash": "8c32b6da4da97e8c3009622df03a3a4e",
   "_docHash": "6610e65d6d600aa982a7732c14b36253",
   "hash": "DwXaU994DhLgo36wXPcoHg2YdzXVrwYmWEgg44Xv7zKW",
   "hederaStatus": "ISSUE",
   "signature": 0,
   "type": "verification_report",
   "policyId": "68c952870fd12e530dddadf8",
   "tag": "save_verification_report_db",
   "schema": "#2321fb67-54e0-464d-bcd5-8dc2dbad2c41&1.0.0",
   "option": {
     "status": "Submitted"
   },
   "relationships": [
     "1758024822.724992000",
     "1758024558.020152392"
   ],
   "owner": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
   "group": "2c6c93e9-d089-4518-9f66-e548df9e0cac",
   "accounts": {
     "default": "0.0.6856934"
   },
   "topicId": "0.0.6856972",
   "messageId": "1758024870.409535000",
   "messageHash": "5rEZTmpPFwFAfWXhfpQyT7yPV3DPBPp3fUEfY388Pmz7",
   "messageIds": [
     "1758024870.409535000"
   ],
   "document": {
     "id": "urn:uuid:23c30e34-2e79-46a2-b1bd-150199a53b4a",
     "type": [
       "VerifiableCredential"
     ],
     "issuer": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936",
     "issuanceDate": "2025-09-16T12:14:13.166Z",
     "@context": [
       "https://www.w3.org/2018/credentials/v1",
       "ipfs://bafkreig74sj6ovdiro5slbtrvz3nnpqddsh64vtiebdro47k77vxesenmm"
     ],
     "credentialSubject": *there are huge payload*,
             "proof": {
       "type": "Ed25519Signature2018",
       "created": "2025-09-16T12:14:15Z",
       "verificationMethod": "did:hedera:testnet:HVfntNBhFWg1TMGPsfnP3QpJazb1oYZsg4tdVbe4i1Me_0.0.6855936#did-root-key",
       "proofPurpose": "assertionMethod",
       "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..PJ8V3NOGKrJ3btTmbES9iLPv15DLD-hjQulq-6CVFBPc6597Mhbufd97r7ZqHIA3XOA2xmWMfFLcgmXxzM8fDg"
     }
   },
   "documentFileId": "68c954aa7d1632a3d92d6493",
   "documentFields": [
     "id",
     "credentialSubject.id",
     "credentialSubject.0.id",
     "issuer",
     "credentialSubject.0.field0",
     "credentialSubject.0.project_details.G5",
     "credentialSubject.0.ref",
     "verifiableCredential.0.credentialSubject.0.field0.field0",
     "verifiableCredential.1.credentialSubject.0.amount",
     "credentialSubject.0.tokenId",
     "credentialSubject.0.serials"
   ],
   "_id": "68c954aa7d1632a3d92d6490",
   "__sourceTag__": "verification_reports_verra_all_reports",
   "id": "68c954aa7d1632a3d92d6490"
 }
],
"blocks": [],
"commonAddons": [
 {
   "id": "cceefdc0-685c-4455-a7f8-123fa65f3472",
   "blockType": "documentsSourceAddon"
 }
],
"fields": [
 {
   "title": "Project",
   "name": "document.credentialSubject.0.ref",
   "tooltip": "",
   "type": "text"
 },
 {
   "title": "Document",
   "name": "document",
   "tooltip": "",
   "type": "button",
   "action": "dialog",
   "url": "",
   "dialogContent": "VC",
   "dialogClass": "",
   "dialogType": "json",
   "bindBlock": "",
   "content": "View Document",
   "uiClass": "link"
 },
 {
   "title": "Status",
   "name": "option.status",
   "tooltip": "",
   "type": "text",
   "width": "250px"
 },
 {
   "title": "Operation",
   "name": "operation",
   "tooltip": "",
   "type": "block",
   "bindGroup": "verification_reports_verra_all_reports",
   "action": "",
   "url": "",
   "dialogContent": "",
   "dialogClass": "",
   "dialogType": "",
   "bindBlock": "mint_token_verra",
   "bindBlocks": [],
   "width": "150px"
 }
],
"viewHistory": false
}
```

**Send the updated payload in the request:**

<mark style="color:green;">`POST`</mark> `http://localhost:4200/api/v1/policies/68c952870fd12e530dddadf8/tag/mint_token_verra/blocks`

With body:

```json5
{
   "document": *changed report data*,
   "tag": "Option_0"
}
```


# API Guideline

We have changed the code avoiding the generalization of the validation status code and any error status code. Instead of 500, we added a specific status code that depends on the situation. Below we provide more information:

### **1xx Informational**

#### **100 Continue:**

The server has received the request headers and the client should proceed to send the request body.

#### **101 Switching Protocols:**

The server understands and is willing to comply with the client's request, via the Upgrade message header field, for a change in the application protocol being used on this connection.

### **2xx Success**

#### **200 OK:**

The request was successful and the server has returned the requested data.

#### **201 Created:**

The request was successful and the server has created a new resource based on the request data.

#### **204 No Content:**

The request was successful but there is no data to return.

### **3xx Redirection**

#### **301 Moved Permanently:**

The requested resource has been moved permanently to a new location.

#### **302 Found:**

The requested resource can be found at a different location temporarily.

#### **304 Not Modified:**

The requested resource has not been modified since the last time it was accessed.

### **4xx Client Error**

#### **400 Bad Request:**

The request was invalid or could not be understood by the server.

#### **401 Unauthorized:**

The request requires user authentication.

#### **403 Forbidden:**

The request is valid but the server refuses to respond due to lack of permission.

#### **404 Not Found:**

The requested resource could not be found on the server.

#### **422 Unprocessable Entity:**

The request was well-formed, but the server could not process it because it contains invalid data.

### **5xx Server Error**

#### **500 Internal Server Error:**

The server encountered an unexpected condition that prevented it from fulfilling the request.

#### **502 Bad Gateway:**

The server received an invalid response from an upstream server while trying to fulfill the request.

#### **503 Service Unavailable:**

The server is currently unable to handle the request due to a temporary overload or maintenance.

#### The most prominent changes are described below

For validation errors, the **422 unprocessable Entity status** code is commonly used, which indicates that the request was well-formed, but contains invalid data. This could include missing or invalid parameters, incorrect data types, or other issues with the data in the request. A JSON payload could be returned with more details about the validation error.

For success with empty data, the 204 No Content status code can be used, indicating that the request was successful, but there is no data to return. This can be useful in cases where the client is performing a DELETE or PUT request, where the server doesn't need to return any additional data.

The **HTTP 202 Accepted status code** indicates that the request has been accepted but has not yet been processed. This status code is often used in APIs to indicate that the server needs more time to process the request or that the request has been queued for processing.

For example, in the context of the Guardian API (<https://github.com/hashgraph/guardian>), the 202 status code could be used when submitting a new transaction or request to the network. The API could immediately return a 202 response indicating that the request has been received and is being processed, and include a link or other information that the client can use to check the status of the request later.

### Naming Conventions for RESTful APIs

RESTful APIs are designed around resources, and using consistent naming conventions for resources, HTTP verbs, and query parameters can make your API easier to understand and use. Here are some guidelines for naming conventions in a RESTful API:

#### **Resources**

Use nouns to represent resources in your API. For example, if you are building an API for managing products, you might use the endpoint /products to represent the collection of all products.

#### **Collection Resources**

Use plural nouns for collection resources. For example, you might use /products to represent a collection of products.

#### **Individual Resources**

Use singular nouns for individual resources. For example, you might use /products/{productId} to represent a specific product.

#### **Hyphenated Names**

Use hyphens to separate words in resource names. For example, you might use /user-profiles to represent a collection of user profiles.

#### **HTTP Verbs**

Use HTTP verbs to represent actions on resources. Here are some common HTTP verbs and their actions:

**GET:**

Retrieve a resource or a collection of resources.

**POST:**

Create a new resource.

**PUT:**

Update an existing resource.

**DELETE:**

Delete a resource.

For example, you might use GET /products to retrieve a list of products, and POST /products to create a new product.

#### Query Parameters

Use query parameters to filter, sort, or paginate resources.

Here are some guidelines for naming query parameters:

1. Use camelCase or snake\_case for query parameter names.
2. Be consistent within your API in the use of query parameter names.
3. Use standard parameter names such as sort\_by, page, or limit whenever possible.

For example, you might use /products?sort\_by=name or /products?sortBy=name to sort products by name.

By following these naming conventions, you can create a consistent and easy-to-use API that will be intuitive for developers to use and understand.\
\
For a complete documentation of name conventions you can follow the recommendations described in this website: <https://restfulapi.net/resource-naming/>


# License

This repo is under Apache 2.0 License. See [LICENSE](https://github.com/hashgraph/guardian/blob/main/LICENSE/README.md) for more information.


# Contact

For any questions, please reach out to the Hashgraph team at:

* Website: <https://hashgraph.com>
* Email: <guardian@hashgraph.com>


# Architecture


# High Level Architecture

This Diagram represents all the micro services at a very high level.

<figure><img src="/files/vE6PgAm9t4RYt5OAA3NP" alt=""><figcaption></figcaption></figure>


# Deep Dive Architecture

This is a Deep Dive Architecture representing Micro Services at Component level.

This repo contains a reference implementation of the Guardian to learn how to use the components for various applications. This reference implementation is designed with modularity so that different components may be swapped out based on various implementation requirements. Please see the Guardian's architecture diagram below:

<figure><img src="/files/GGXMZQegmxaPe9ZGZPZ5" alt=""><figcaption></figcaption></figure>


# Policies,Projects and Topics Mapping Architecture

**Note:**

Guardian data migration is supported for published Policy instances which are yet to generate any data, i.e. are 'empty'.

As visible from the below Topic Architecture diagram, for each published Policy instance, irrespective of it being a new version of existing Policy or a new Policy altogether, a corresponding new Topic is created in Hedera. This action is coupled with a notification message sent to an appropriate topic, for the former it is the 'new version' message which is posted into the top-level original Policy Topic, for the latter it is the 'new policy' message which is posted into the Standard Registry Topic.

When Policy instance data is migrated into a new Policy instance, Guardian traverses all corresponding Topics and reposts all the messages, and resubmits all the previously generated documents into the new Topic structure (belonging to the new Policy instance). The documents may also be re-signed by the new Standard Registry if they have been modified (extended) during migration. Each of the messages and documents refer to original message/document in the corresponding "evidence" section of the document JSON.

Thus, the newly migrated data is usable as a stand-alone data tree and is backward compatible with all existing Guardian and 3rd party tools, while at the same time the original trail of documents is referenced and accessible which allows for incontrovertible trail of evidence for data provenance.

<figure><img src="/files/VkZdwDh4JyIIMKfpQxXh" alt=""><figcaption></figcaption></figure>


# MRV Splitting Logic

<figure><img src="/files/WFkxzHaKU3724ki0rF4P" alt=""><figcaption></figcaption></figure>


# Internal (with Vault)Signing Sequence Diagram

<figure><img src="/files/7cBtZdSPcFoMFFlV0PVZ" alt=""><figcaption></figcaption></figure>


# FireBlocks Signing Sequence Diagram

<figure><img src="/files/qIpqGkBvmE6JOyWMLYy4" alt=""><figcaption></figcaption></figure>


# Standard Registry

The Standard Registry (SR) is an accredited authority responsible for creating, managing, and publishing standards, methodologies, and policies on the Guardian platform. It serves as the trusted entity that defines how sustainability-related digital assets (like carbon credits, renewable energy certificates, or other ESG tokens) are structured, verified, and issued.

**Key Functions of the Standard Registry**

1. **Methodology Management**
   * Develops and registers new methodologies for environmental or sustainability processes (e.g., carbon reduction, reforestation, renewable energy tracking).
   * Ensures methodologies align with global compliance frameworks and best practices.
2. **Policy Creation & Governance**
   * Publishes policies that define the rules and workflows for issuing and verifying Verifiable Credentials (VCs) and Verifiable Presentations (VPs).
   * Establishes how data flows between participants (project developers, auditors, validators, and buyers).
3. **Certification Authority**
   * Issues schemas, policies, and credentials that other participants must follow.
   * Provides official recognition and assurance of trust in methodologies.
4. **Ecosystem Enablement**
   * Onboards project developers, auditors, and participants to operate within its defined policies.
   * Ensures transparency, traceability, and standardization across environmental markets.


# Schemas

A Schema in Guardian is a structured data definition that describes the format, attributes, and validation rules for Verifiable Credentials (VCs) and Verifiable Presentations (VPs) within policies and methodologies.

Schemas ensure that all participants (Standard Registries, Project Developers, Auditors, Validators, Buyers, etc.) use a common, consistent, and machine-readable structure when exchanging sustainability-related data on the Hedera network.

#### **Key Characteristics of Schemas**

1. **Standardized Data Model**
   * Defines the fields, data types, and relationships for a specific entity (e.g., a project description, monitoring report, or carbon credit issuance record).
   * Guarantees interoperability across policies, methodologies, and different Standard Registries.
2. **Validation Rules**
   * Enforces constraints like required fields, value ranges, or enumerations.
   * Ensures data integrity and consistency before being issued on-chain.
3. **Reusability**
   * Once published, schemas can be reused across multiple policies and methodologies.
   * Promotes standardization across ecosystems (e.g., all carbon projects may use the same Emission Reduction Schema).
4. **Version Control**
   * Schemas are versioned, enabling updates or modifications without breaking existing data structures.
   * Allows migration from old to new schema versions when standards evolve.

#### **Types of Schemas in Guardian**

* **System Schemas** → Provided by Guardian (for core functions like DID, VP, VC, token definitions).
* **Custom Schemas** → Defined by Standard Registries or methodology authors for their specific workflows (e.g., Project Registration Schema, Monitoring Report Schema).
* **Policy-bound Schemas** → Linked directly to a policy to structure its credentials and reports.


# Types of Schemas

There are four types of Schemas:

1. [System Schemas](#system-schemas)
2. [Policy Schemas](#policy-schemas)
3. [Tag Schemas](#tag-schemas)
4. [Module Schemas](#module-schemas)

To display System / Policy Schemas in the GUI, we have added a toggle in the Schemas tab.

<figure><img src="/files/ks50byn0wmmZfGLJ2RV4" alt=""><figcaption></figcaption></figure>

## System Schemas

Whenever an account is created, System Schemas are generated automatically.

<figure><img src="/files/2fO3NClKCw3ze9nbUeFt" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Note: By default System Schemas cannot be edited/deleted.
{% endhint %}

## Policy Schemas <a href="#policy-schemas" id="policy-schemas"></a>

This is the second option in the Schemas tab. This option displays all the Policy Schemas related to all the created/imported Policies in the Policies tab.

The below screenshot shows the Policy Schemas of an imported Policy (i.e. iRec).

<figure><img src="/files/8nrSt8tUp0qSWlFrUI6r" alt=""><figcaption></figcaption></figure>

We also have a filter, where by default, all the Schemas of Policies are shown. We can also select a particular Policy to show the Schemas of the selected Policy.

<figure><img src="/files/IF2Z8XMEOY3Vs2Y0osDO" alt=""><figcaption></figcaption></figure>

## Tag Schemas

Tags can have attached/linked documents. To add a document to the tag a schema is required. Such documents can be found under the [**Tag Schemas**](/guardian/standard-registry/schemas/tag-schema) section.

## Module Schemas

Module schemas needs to define minimum set of fields in module variable with type “schema”.

### Creation of Schemas

To create module schema, we need to click on Create New button:

<figure><img src="/files/KC2yRI5FJgrvVe6ru35t" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/HaLxe6Elc9oqw8g5iQ1B" alt=""><figcaption></figcaption></figure>

### Using schemas:

Select module schema in “BaseSchema” field in module variables section

<figure><img src="/files/fwzlm8KxcBXuTdG1r1MP" alt=""><figcaption></figcaption></figure>


# Available Schema Data Types

## **Embracing GBBC Specifications for Universal Data Comparability**

In the Guardian, the Property Glossary serves a pivotal role in harmonizing data across the entire ecosystem. Leveraging the standards set forth in the [GBBC dMRV Specification](https://gbbcouncil.org/wp-content/uploads/2023/09/Digital-Measurement-Reporting-Verification-dMRV-Framework.pdf) (and beyond), the glossary establishes a unified framework for interpreting and mapping data, ensuring that information collected through various schema formats remains consistent, comparable, and searchable.

## **The Need for Standardized Data Mapping**

The complexity of environmental reporting and digital asset management is compounded when dealing with varied methodologies and schema designs. To address this, the Guardian implements a standardized approach to data mapping, allowing for effective comparison and analysis of project data, regardless of its original schema format. This standardization is vital for:

1. **Ensuring Consistency:** Regardless of how data is formatted in individual schemas, standardizing property definitions ensures a consistent approach to interpreting and comparing data.
2. **Facilitating Comparability:** By using a common language for data properties, the Guardian enables users to effectively compare and analyze data from similar or different methodologies.
3. **Enhancing Searchability:** Standardized properties allow for more efficient data retrieval, making it easier to locate specific information across various projects and schemas.

## **Role of the Property Glossary**

The Property Glossary in MGS is more than just a list of definitions; it is a tool for aligning data across the platform. It includes a table of **Standardized Property Definitions.** Drawing from the GBBC Specification, the glossary provides clear definitions for each property, ensuring a common understanding across the platform.

**Introduction**

In the realm of digital environmental assets and carbon offset tokens, data is king. The essence of creating verifiable and trustworthy digital assets lies in the quality and structure of the underlying data. This is where the concept of "Schema Types" comes into play. Schemas serve as the backbone of data organization, ensuring that every piece of information adheres to a predefined format, thereby maintaining consistency, accuracy, and reliability.

**Purpose of Schema Types**

Schema Types are not just about data organization; they are about setting a standard for data integrity and trustworthiness. By defining clear structures and formats for data entry, storage, and retrieval, schemas facilitate:

1. **Standardization and Uniformity:** Ensuring all data across various projects and methodologies conforms to a consistent structure, enabling seamless integration and comparison.
2. **Flexibility and Customization:** Catering to diverse needs by allowing modifications to fit specific project requirements without compromising data integrity.
3. **Efficient Data Management:** Streamlining the process of data handling, from input to analysis, ensuring that data-driven decisions are based on accurate and reliable information.

**Role in Digital Environmental Assets**

The utilization of Schema Types is pivotal for the lifecycle of digital environmental assets. From the initial stages of data collection to the final phases of token creation and verification, schemas ensure that each step is backed by solid, verifiable data. This approach not only enhances the credibility of the digital assets but also boosts confidence among stakeholders in the carbon market ecosystem.

| Schema Type | Definition                                                                                                                                  | Example Input                                                                                                                                          |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| String      | A string is a data type used in programming, such as an integer and floating point unit, but is used to represent text rather than numbers. | I ate 3 hamburgers.                                                                                                                                    |
| Number      | A whole number is an integer that is 0 or greater.                                                                                          | 0, 1, 2, 3, or 4.                                                                                                                                      |
| Integer     | An integer is a whole number (not a fraction) that can be positive, negative, or zero.                                                      | 10, 0, -25, 5148.                                                                                                                                      |
| Boolean     | Boolean, or boolean logic, is a subset of algebra used for creating true/false statements.                                                  | True or False.                                                                                                                                         |
| Date        | Specifies a calendar date.                                                                                                                  | 2023-01-01                                                                                                                                             |
| Time        | Specifies a time.                                                                                                                           | 12:00 AM.                                                                                                                                              |
| DateTime    | Specifies a calendar date and a time.                                                                                                       | 2022-03-25T12:10:33.916Z                                                                                                                               |
| Duration    | Specifies a calendar date range calendar.                                                                                                   | P1D (1 day), P2W (2 weeks), P3M (3 months), P4Y (4 years), P1Y1D (1 year + 1 day)                                                                      |
| URL         | Specifies a website.                                                                                                                        | <https://github.com/hashgraph/guardian>.                                                                                                               |
| Email       | Specifies a email address.                                                                                                                  | <email@exampleemail.com>.                                                                                                                              |
| Image       | Specifies IPFS URL of an uploaded image.                                                                                                    | [ipfs://bafkreiebnkjylfsdds5oicxpk5vdink5tduwbxed5552xcmeyrbzpewfuu](https://ipfs.io/ipfs/bafkreiebnkjylfsdds5oicxpk5vdink5tduwbxed5552xcmeyrbzpewfuu) |
| Account     | Specifies Hedera Account name                                                                                                               | Custom Account                                                                                                                                         |
| Prefix      | Specifies adding Units in front of quantity                                                                                                 | Rs                                                                                                                                                     |
| Postfix     | Specifies adding Units after the quantity                                                                                                   | Litres, Kgs,$                                                                                                                                          |
| Enum        | Specifies values to be added                                                                                                                | Option 1, Option 2                                                                                                                                     |
| Help Text   | Define some help text and set some text parameters like bold, text size, text color                                                         | Text Field                                                                                                                                             |
| GeoJSON     | Define to add polygons, lines on map                                                                                                        | Alza\_....                                                                                                                                             |
| URI         | Example link to ipfs files                                                                                                                  | ${schema}://{auth}/….                                                                                                                                  |
| SentinelHub | Define Geographic rastery imagery coordinates                                                                                               | Height, Width, From and To Date.                                                                                                                       |
| Table       | Add CSV-based tables to documents                                                                                                           | CSV file                                                                                                                                               |

Each of the above field types can be marked as either Marked or optional by checking the Required Field checkbox.

{% hint style="info" %}
**Note: Auto Calculate fields**

Any field can be set to "Auto Calculate" mode. When enabled, the field value is computed from a JavaScript expression that can reference sibling fields by name. The expression editor includes:

* A help panel with available fields, operators, functions, and examples (click **?** to open)
* Real-time validation that catches syntax errors and undefined references
* Click-to-insert for field names and functions

For details and the `table` helper, see [Table Data Input Field with AutoCalculate](/guardian/standard-registry/schemas/available-schema-types/table-data-input-field/table-data-input-field-with-autocalculate).
{% endhint %}

{% hint style="info" %}
**Note: Important points to be noted when "Account" type is selected:**

1. Account field type need to be referred in ‘tokenConfirmationBlock’ and ‘tokenActionBlock’. They can be present both in the parent and child documents.
2. If there are multiple fields of the ‘Account’ with the same name, then the value from the most immediate scope, i.e. from the current (‘child’) document is used.
   {% endhint %}

{% hint style="info" %}
**Note: Important points to be noted when "Enum" type is selected:**

1. Enum values can be added by editing or by importing it from link or from file.
2. If we are importing files by URL. The response should be ({"enum": \["Option1", "Option2", "Option3"]}) or has same format such as importing file (Options separated by new line symbol).

Example of URL which has correct format: <https://ipfs.io/ipfs/bafkreihgbx6fsqup4psfbzjcf57zjdbfwisbjbsqzvwlg4hgx5s5xyqwzm>

3\. If we put more than five options, it will be automatically loaded to IPFS.
{% endhint %}

{% hint style="info" %}
**Note: Important points to be noted when "GeoJSON" type is selected:**

1. Click on map and place the marker’s, polygons, lines.
2. Polygons and lines can be placed by double clicking on map.
3. Right Click on the map will remove temporary points for polygons and lines
4. View type can also be changed by pasting the GeoJSON.
5. We can upload .kml, .json files to add locations. More details on this can be found in this [doc](/guardian/standard-registry/schemas/how-to-handle-large-location-files).
   {% endhint %}

{% hint style="info" %}
**Note: Important points to be noted when "String" type is selected:**

1. Pattern input field is added in the advanced mode configuration.

Detailed information for patterns is available on <https://json-schema.org/understanding-json-schema/reference/regular_expressions.html>.
{% endhint %}

{% hint style="info" %}
For all fields of type string with different formats (e.g., `url`, `uri`, `file`), an IPFS validator has been added.

* If the value looks like an IPFS link or must be an IPFS link (depending on the format’s internal validation), the field will validate against this requirement.
* The validation is applied only for published policies. For draft policies, validation is disabled.
  {% endhint %}

<figure><img src="/files/kWSgqD7erojwbLQoiLUo" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
For geoJSON fields :\\

* A new property `availableOptions` has been added.
* On the UI, a dropdown list is displayed to select which geoJSON types are available.
* If certain types are selected, then when creating a document, the `geoJSON` field will only allow choosing those specific types.
* Validation has also been added for the `geoJSON` field to ensure that values comply with the rules of the selected geoJSON type.
  {% endhint %}


# Table Data Input Field

A Table field lets you add CSV-based tables to documents:

* Import a CSV file
* Edit or fill it by manually
* Use table data in calculations with other fields
* View and download results in both Guardian and Indexer.

### 1. Add this field to a policy schema

Add a Table-type field to a schema so users can work with it in forms.

Setup:

* Choose Field type: Table.
* Multiple table fields can be added in one document.
* All table fields can participate in calculations (cross-table formulas, sums, links with other fields, etc.).

<figure><img src="/files/JuO5JerxNcKHaIG6Jyxb" alt=""><figcaption></figcaption></figure>

### 2. Use the field while filling the form

When added to a schema, the table is shown to a user during data entry.

Available options:

* Import CSV: load a file and preview the first rows/columns.
* Export/Download CSV: download the current state of the table.
* Edit: open the table in a dialog and update cells.
* Create manually: start with an empty table and fill it by hand.

<figure><img src="/files/DccLC5vZPgewqezV4oSt" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/9SX4sJacaoZnmUETfHQ4" alt=""><figcaption></figcaption></figure>

### 3. Run calculations (inside a table and with other fields)

Use table data in document formulas and logic.

Options:

* Inside a table – row/column calculations (e.g., sums, averages, etc.).
* With other form fields – via:
* AutoCalculate field (automatic calculation)
* Custom Logic Block (custom rules/logic)

<figure><img src="/files/VVpwVVqEWq0NviFdW1mL" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/2fmBD4x6pYd3Y8gs8xeA" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/nW4QpmrhZ2CEmwouIvBW" alt=""><figcaption></figcaption></figure>

### 4. Save a prefilled table as a Draft

Save an unfinished form with imported/entered table data and return to it later.

<figure><img src="/files/KqXZbZBy49Ibjh4ZKtyW" alt=""><figcaption></figcaption></figure>

### 5. View and download results in document view

What it does:

* In Guardian, VC document view shows tables and calculated values.
* In Indexer, the same table is available for viewing and downloading.

<figure><img src="/files/UcnxYBJ3sRT2dpPwwiWl" alt=""><figcaption></figcaption></figure>

### 6. Limits and performance

* If the table size exceeds 10 MB, manual editing in the UI is not available.
* To edit:, download the CSV, update it externally,then re-import.
* Calculations still work above 10 MB, but:
* Performance may be slower
* Preview is limited to the first rows/columns

<figure><img src="/files/a4KzMTtcU7PF5XyXQnZl" alt=""><figcaption></figcaption></figure>

## Demo Video

[Youtube](https://youtu.be/m3waGJ7qgs4?si=0bEJusqaQ2hPEU4t\&t=121)


# Table Data Input Field with AutoCalculate

## 1. Overview

The Table field lets you:

* Import CSV data
* Edit or fill it manually
* Use the data in AutoCalculate expressions

## 2. Expression Engine

AutoCalculate expressions are evaluated as **JavaScript**. The expression is wrapped in `with (this) { return <expression> }` where `this` is the current document, so you can reference sibling fields directly by name.

### 2.1 Expression Help Panel

When editing an Auto Calculate expression, a **?** help icon appears next to the "Edit expression" button. Hovering over it shows a quick reference tooltip:

Click "Edit expression" to open the Code Editor. Click the **?** icon in the editor header to open the Expression Help panel on the right side:

The help panel provides:

* **Available Fields** — clickable chips of sibling field names; click to insert at cursor
* **Operators** — all supported JS operators with labels
* **Functions** — grouped by category (Math, Array, Type conversion) with click-to-insert
* **Parameters** — the `table` helper and its methods with usage descriptions
* **Examples** — ready-to-use expression patterns covering common scenarios

The editor and help panel scroll independently, so you can browse the reference while writing your expression.

### 2.2 Supported Functions

| Category        | Functions                                                                                                                                                                                       |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Math            | `Math.abs()`, `Math.round()`, `Math.floor()`, `Math.ceil()`, `Math.sqrt()`, `Math.pow()`, `Math.log()`, `Math.log10()`, `Math.exp()`, `Math.min()`, `Math.max()`, `Math.trunc()`, `Math.sign()` |
| Array           | `.reduce()`, `.filter()`, `.map()`, `.length`                                                                                                                                                   |
| Type conversion | `Number()`, `String()`, `parseFloat()`, `parseInt()`                                                                                                                                            |

### 2.3 Expression Validation

The editor validates expressions by compiling and executing them against mock data, using the same mechanism as the backend. This catches:

* Syntax errors (unmatched parentheses, invalid operators)
* Undefined functions (e.g. `SUM()` is not valid — use `.reduce()` instead)
* Undefined field references

If validation reports a warning, you can still save the expression using the **Save Anyway** button.

### 2.4 Nested Schema Fields

If a sibling field references another schema (isRef), you can access its sub-fields using dot notation:

```
subSchema.width * subSchema.height
```

### 2.5 Local Variables (IIFE)

Since expressions must be a single return value, use an IIFE for local variables:

```
(() => { const tax = price * 0.2; return price + tax; })()
```

## 3. Expression Helper: table

Inside AutoCalculate expressions, a helper object named table is available with the following functions:

* table.keys(tbl) → string\[] – returns ordered column names
* table.rows(tbl) → Record\<string,string>\[] – returns an array of row objects (data rows only)
* table.cell(tbl, rowIndex, keyOrIndex) → unknown – accesses a cell by row and column
* table.col(tbl, keyOrIndex) → unknown\[] – returns a whole column (by name or index)
* table.num(value) → number – tolerant number conversion (''/text → 0; '1,23' → 1.23)

{% hint style="info" %}
Note: Expressions run as JavaScript with the current document bound as this, so you can reference table fields directly by their schema names (e.g., field20).
{% endhint %}

## 4. Headers & Indexing

* The first CSV row is treated as the header (column names).
* Data starts at the second CSV row; in the API this is row index 0.
* Row and column indices are zero-based (0, 1, 2, …).
* If your CSV has no meaningful headers, the first row is still used as the header. To avoid relying on header text, use numeric column indices (0, 1, 2, …).

## 5. Cell Map Example

Sample table:

| Product | Qty | Price |
| ------- | --- | ----- |
| 1       | 1   | 3     |
| 2       | 4   | 5     |
| 3       | 6   | 8     |

Coordinates of data (zero-based):

* (0,0)=1, (0,1)=1, (0,2)=3
* (1,0)=2, (1,1)=4, (1,2)=5
* (2,0)=3, (2,1)=6, (2,2)=8

## 6. Access Patterns

### 5.1 By Column Name

table.col(field20, 'Price') // entire 'Price' column from table field20

### 5.2 By Column Index (no headers dependence)

table.col(field20, 2) // third column (index 2)

### 5.3 Single Cell by Coordinates

table.cell(field20, 1, 'Qty') // row 1 (second data row), column 'Qty'

table.cell(field20, 2, 2) // row 2, column index 2

## 7. In-Table Calculations (Single Table)

### 6.1 Sum of a Named Column (Price)

table.col(field20, 'Price').reduce((s, v) => s + table.num(v), 0)

### 6.2 Sum of a Column by Index (third column)

table.col(field20, 2).reduce((s, v) => s + table.num(v), 0)

### 6.3 Specific Cells + Power

Access cells by coordinates only (works even if headers are not meaningful):

```
Math.pow(
  table.num(table.cell(field20, 1, 1)) +  // Qty[1]
  table.num(table.cell(field20, 2, 2)),   // Price[2]
  2
)
```

## 8. Cross-Table Calculations & Other Fields

### 7.1 Sum a column from field20, add a column from field30, add a numeric form field field21, then square the total

```
Math.pow(
  // sum of 'Price' from field20
  table.col(field20, 'Price').reduce((s, v) => s + table.num(v), 0) +
  // sum of 'Price' from field30
  table.col(field30, 'Price').reduce((s, v) => s + table.num(v), 0) +
  // numeric form field
  field21,
  2
)
```

### 7.2 Index-Only Variant (no header dependency)

```
Math.pow(
  table.col(field20, 2).reduce((s, v) => s + table.num(v), 0) +
  table.col(field30, 1).reduce((s, v) => s + table.num(v), 0) +
  table.num(field21),
  2
)
```

## 9. Power & Root Examples

* Square: (a + b) \*\* 2 or Math.pow(a + b, 2)
* Square root: Math.sqrt(x) // same as Math.pow(x, 0.5)
* (table.num(table.cell(field20, 0, 2)) \*\* 2)
* Math.sqrt(table.num(table.cell(field20, 2, 2)))

\
\\


# Custom Logic Block & Tables

### 1. Purpose

The Custom Logic Block lets you run custom JavaScript or Python over input documents and/or sources and return either:

* the same document with updated fields (Pass original: ON), or
* a new VC (unsigned or signed) (Pass original: OFF).

Access to table data inside expressions is identical to AutoCalculate and uses the table helper:

* table.keys(tbl) → column names
* table.col(tbl, keyOrIndex) → column values
* table.rows(tbl) → data rows
* table.cell(tbl, rowIndex, keyOrIndex) → a cell
* table.num(value) → safe number conversion

{% hint style="info" %}
Note: the expression has access to documents, sources, table, and done(result) to return the result.
{% endhint %}

### 2. When to use each mode

#### Pass original: ON

* You return the entire document (or an array) after modifications.
* Does not create a new VC, does not validate by schema, and does not sign.
* Easiest and most reliable way to “compute and write a field” in an existing VC.

#### Pass original: OFF

* Creates a new VC (unsigned or signed).
* Requires additional setup:
* Unsigned VC → return only the subject (or an array of subjects). Must include valid id, type, @context (or set outputSchema, which provides @context/type).
* Signed VC → set outputSchema, configure documentSigner, and return JSON matching the schema.

{% hint style="info" %}
If any of these are missing, VC build/validation may fail (e.g., “Cannot read properties of undefined (reading 'codeVersion')”, “…getId…”).
{% endhint %}

### 3. Working expressions (Pass original: ON)

#### 3.1. Subtotal by table and grand total with a form field

* Sums Qty \* Price per row.
* Adds a numeric form field field21.
* Writes results to calcSubtotal and calcTotal in the subject.

```
(() => {
  const list = Array.isArray(documents) ? documents : [documents];

  const updated = list.map((doc) => {
    const cs = Array.isArray(doc?.document?.credentialSubject)
      ? doc.document.credentialSubject[0]
      : doc?.document?.credentialSubject;
    if (!cs) return doc;

    const tableValue = cs?.field1?.field20 ?? cs?.field20;
    const extraValue = cs?.field1?.field21 ?? cs?.field21;

    const allRows = table.rows(tableValue) || [];
    const rows = allRows.filter(r => (r['Product']) !== 'Product');

    const calcSubtotal = rows.reduce((sum, r) => {
      const qty   = table.num(r['Qty']);
      const price = table.num(r['Price']);
      return sum + qty * price;
    }, 0);

    const calcTotal = calcSubtotal + table.num(extraValue);

    cs.calcSubtotal = calcSubtotal;
    cs.calcTotal = calcTotal;

    return doc;
  });

  done(Array.isArray(documents) ? updated : updated[0]);
})();

```

#### 3.2. Sum a column by name and write to field21

* Finds the “Price” column by name.
* Sums values and writes the result to field21 (works with nested/flat schema).

```
(() => {
  const list = Array.isArray(documents) ? documents : [documents];

  const updated = list.map((doc) => {
    const cs = Array.isArray(doc?.document?.credentialSubject)
      ? doc.document.credentialSubject[0]
      : doc?.document?.credentialSubject;
    if (!cs) return doc;

    const tbl = cs?.field1?.field20 ?? cs?.field20;

    let sumPrice = 0;
    if (tbl) {
      const keys = table.keys(tbl) || [];
      const priceKey = keys.find(k => String(k).trim() === 'Price');
      if (priceKey) {
        const col = table.col(tbl, priceKey) || [];
        sumPrice = col.reduce((s, v) => s + table.num(v), 0);
      }
    }

    if (cs?.field1) cs.field1.field21 = sumPrice;
    else cs.field21 = sumPrice;

    return doc;
  });

  done(Array.isArray(documents) ? updated : updated[0]);
})();

```

#### 3.3. Index-only

* Sums the third column (index 2) by index only.
* Writes the result to field21.

```
(() => {
  const list = Array.isArray(documents) ? documents : [documents];

  const updated = list.map((doc) => {
    const cs = Array.isArray(doc?.document?.credentialSubject)
      ? doc.document.credentialSubject[0]
      : doc?.document?.credentialSubject;
    if (!cs) return doc;

    const tbl = cs?.field1?.field20 ?? cs?.field20;

    let total = 0;
    if (tbl) {
      const col = table.col(tbl, 2) || [];
      total = col.reduce((s, v) => s + table.num(v), 0);
    }

    if (cs?.field1) cs.field1.field21 = total;
    else cs.field21 = total;

    return doc;
  });

  done(Array.isArray(documents) ? updated : updated[0]);
})();

```

### 4. Doing the same with Pass original: OFF

#### Unsigned VC: ON

Return only credentialSubject (or an array). Make sure you provide valid:

* id (can be set or generated),
* type, @context (may come from outputSchema if set in the block).

Without these, raw VC build will fail.

#### Signed VC (Unsigned: OFF)

* Set outputSchema.
* Return a subject that matches the schema.
* Configure documentSigner.

The block will then:

* validate the subject against the schema,
* add service fields,
* sign the VC.

Any mismatch with outputSchema will cause validation/signing errors.

\\


# Importing Excel Tables into the Project Schema in VM0033 methodology

To test this feature, VM0033 schemas excel file containing multiple pages was provided as an example.

Each page in the Excel file must be converted into a CSV file, and each CSV file should be uploaded as a separate table field. T

The name of each page can be used as the corresponding table field name.

In policy **VM0033**, three table fields were added to the **Project Description (Auto)** schema.\
Screenshots of the *8.2ProjectEmissions* Excel page and the corresponding table in the VC document are provided for reference.

<figure><img src="/files/NeuhXSTLh1IjQZmTxmXw" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/BY27U25g9owiaNEUX6jd" alt=""><figcaption></figcaption></figure>

#### 5.1 Adding Table Fields to the Policy Schema

In the example of policy **VM0033**, three table fields were added to the **Project Description (Auto)** schema. Each table field retains the same name as in the original Excel file.

<figure><img src="/files/XLRIUx7TR7xuMeB1svm5" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/BhvFpMeBjNNwe2wYQb2G" alt=""><figcaption></figcaption></figure>

#### 5.2 Importing Converted CSV Files into Table Fields

Log in as the **Project Proponent**, then create a new project by clicking the **“New Project”** button.

Within the form, import the converted CSV files into their respective table fields.

<figure><img src="/files/vSuMUyy0nfBrFQfmkZr5" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/76XCMFe6gsnD3TGAVKnL" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/V2nqJaihkY3MDSTWn2QX" alt=""><figcaption></figcaption></figure>

After loading the files, please review the first rows/columns.

<figure><img src="/files/gK4ul8yNupzjbor4YNIP" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZZ2axI40Z1Js0UZwXbip" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/u5iCJleUgnuM8MTwutZH" alt=""><figcaption></figcaption></figure>

#### 5.3 Viewing Tables in the VC Document

The VC document displays the imported tables. To view them, click the **“Open Table”** button.

<figure><img src="/files/z4cFCusjzxNBsQdRArpL" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Ebql8XcKdvuPwG0eE3TY" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/6UTiljDDqmtwyFElxG12" alt=""><figcaption></figcaption></figure>


# APIs related


# Download file by id

<mark style="color:green;">`GET`</mark> `/artifacts/files/{fileId}`

Returns file from GridFS

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |

**Body**

| Name   | Type   | Description |
| ------ | ------ | ----------- |
| fileId | string | File ID     |

**Response**

{% tabs %}
{% tab title="401" %}

```json5
description: Unauthorized.
```

{% endtab %}

{% tab title="403" %}

```json5
{
  description: Forbidden.
}
```

{% endtab %}
{% endtabs %}


# Existing file \_id to overwrite (optional)

<mark style="color:green;">`POST`</mark> `/artifacts/files`

Uploads/overwrites file in GridFS

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |

**Response**

{% tabs %}
{% tab title="401" %}

```json5
description: Unauthorized.
```

{% endtab %}

{% tab title="403" %}

```json5
{
  description: Forbidden.
}
```

{% endtab %}
{% endtabs %}


# Add file to ipfs directly

<mark style="color:green;">`POST`</mark> `/ipfs/file/direct`

Add file to ipfs directly

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |

**Response**

{% tabs %}
{% tab title="200" %}

```json5
description: Successful operation.
          content:
            application/json:
              schema:
                type: string
```

{% endtab %}

{% tab title="401" %}

```json5
{
  description: Unauthorized.
}
```

{% endtab %}

{% tab title="403" %}

```json5
{
description: Forbidden.
}
```

{% endtab %}

{% tab title="500" %}

```json5
description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalServerErrorDTO'
```

{% endtab %}
{% endtabs %}


# Deletes file from GridFS by id

Deletes file from GridFS by \_id

<mark style="color:red;">`DELETE`</mark> `/artifacts/files/{fileId}`

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |

**Body**

| Name   | Type   | Description |
| ------ | ------ | ----------- |
| fileId | string | File \_id   |

**Response**

{% tabs %}
{% tab title="401" %}

```json5
description: Unauthorized.
```

{% endtab %}

{% tab title="403" %}

```json5
description: Forbidden.
```

{% endtab %}
{% endtabs %}


# Property Glossary

<table><thead><tr><th width="313">Property</th><th width="130">Type</th><th width="290">Description</th></tr></thead><tbody><tr><td>AccountableImpactOrganization.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>AccountableImpactOrganization.name</td><td>string</td><td>Name of the entity</td></tr><tr><td>AccountableImpactOrganization.description</td><td>string</td><td>Description of the entity</td></tr><tr><td>AccountableImpactOrganization.addresses</td><td>array</td><td>Collection of addresses</td></tr><tr><td>AccountableImpactOrganization.owners</td><td>array</td><td>Collection of owners</td></tr><tr><td>AccountableImpactOrganization.country</td><td>Unknown Type</td><td>Country of the address</td></tr><tr><td>AccountableImpactOrganization.region</td><td>Unknown Type</td><td>Region where project is located</td></tr><tr><td>AccountableImpactOrganization.informationLink</td><td>Unknown Type</td><td>Link with project info</td></tr><tr><td>AccountableImpactOrganization.mediaLinks</td><td>array</td><td>Collection of media links</td></tr><tr><td>AccountableImpactOrganization.attestations</td><td>array</td><td>Collection of attestations</td></tr><tr><td>AccountableImpactOrganization.activityImpactModules</td><td>array</td><td>Collection of activity impact modules</td></tr><tr><td>ActivityImpactModule.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>ActivityImpactModule.aioId</td><td>string</td><td></td></tr><tr><td>ActivityImpactModule.name</td><td>string</td><td>Name of the entity</td></tr><tr><td>ActivityImpactModule.classificationCategory</td><td>Unknown Type</td><td>Project classification category - Carbon Avoidance, Reduction, Removal</td></tr><tr><td>ActivityImpactModule.classificationMethod</td><td>Unknown Type</td><td>Classification method - Natural, Technological, Both</td></tr><tr><td>ActivityImpactModule.benefitCategory</td><td>Unknown Type</td><td>Benefit category - Climate Action, Zero Hunger, etc.</td></tr><tr><td>ActivityImpactModule.projectScope</td><td>Unknown Type</td><td>Project scope - Agriculture, Carbon Capture, etc.</td></tr><tr><td>ActivityImpactModule.projectType</td><td>Unknown Type</td><td>Project type - Afforestation, Cookstoves, etc.</td></tr><tr><td>ActivityImpactModule.projectScale</td><td>Unknown Type</td><td>Project scale - Micro, Small, Medium, Large</td></tr><tr><td>ActivityImpactModule.arbId</td><td>string</td><td>CA Air Resources Board ID</td></tr><tr><td>ActivityImpactModule.geographicLocation</td><td>Unknown Type</td><td>Geographic location of project</td></tr><tr><td>ActivityImpactModule.firstYearIssuance</td><td>string</td><td>First year credits issued</td></tr><tr><td>ActivityImpactModule.registryProjectId</td><td>string</td><td>Project ID on registry</td></tr><tr><td>ActivityImpactModule.developers</td><td>array</td><td>Collection of developers</td></tr><tr><td>ActivityImpactModule.sponsors</td><td>array</td><td>Collection of sponsors</td></tr><tr><td>ActivityImpactModule.claimSources</td><td>array</td><td>Collection of claim sources</td></tr><tr><td>ActivityImpactModule.impactClaims</td><td>array</td><td>Collection of impact claims</td></tr><tr><td>ActivityImpactModule.mrvExtensions</td><td>array</td><td>Collection of MRV extensions</td></tr><tr><td>ActivityImpactModule.validations</td><td>array</td><td>Collection of validations</td></tr><tr><td>ActivityImpactModule.attestations</td><td>array</td><td>Collection of attestations</td></tr><tr><td>ActivityImpactModule.accountableImpactOrganization</td><td>Unknown Type</td><td></td></tr><tr><td>Address.addressType</td><td>Unknown Type</td><td>Type of address - Physical, Legal, Mailing</td></tr><tr><td>Address.addressLines</td><td>array</td><td>Address lines</td></tr><tr><td>Address.city</td><td>string</td><td>City of the address</td></tr><tr><td>Address.state</td><td>string</td><td>State of the address</td></tr><tr><td>Address.zip</td><td>string</td><td></td></tr><tr><td>Address.country</td><td>string</td><td>Country of the address</td></tr><tr><td>Any.typeUrl</td><td>string</td><td></td></tr><tr><td>Any.value</td><td>array</td><td></td></tr><tr><td>Attestation.tag</td><td>Unknown Type</td><td></td></tr><tr><td>Attestation.type</td><td>Unknown Type</td><td></td></tr><tr><td>Attestation.proofType</td><td>Unknown Type</td><td></td></tr><tr><td>Attestation.attestor</td><td>string</td><td></td></tr><tr><td>Attestation.signature</td><td>Unknown Type</td><td></td></tr><tr><td>Audits.auditDate</td><td>Unknown Type</td><td>Last audit date</td></tr><tr><td>Audits.auditReports</td><td>array</td><td>Collection of audit report links</td></tr><tr><td>CRU.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>CRU.quantity</td><td>string</td><td>Quantity of credit</td></tr><tr><td>CRU.unit</td><td>Unknown Type</td><td>Unit of credit</td></tr><tr><td>CRU.ownerId</td><td>string</td><td></td></tr><tr><td>CRU.listingAgentId</td><td>string</td><td></td></tr><tr><td>CRU.coreCarbonPrinciples</td><td>Unknown Type</td><td></td></tr><tr><td>CRU.climateLabels</td><td>array</td><td>Collection of climate labels</td></tr><tr><td>CRU.status</td><td>Unknown Type</td><td>Status of credit - Active, Inactive, etc.</td></tr><tr><td>CRU.referencedCredit</td><td>Unknown Type</td><td>Details of referenced credit</td></tr><tr><td>CRU.appliedToId</td><td>string</td><td>Identifier credit was applied to</td></tr><tr><td>CRU.processedClaimId</td><td>string</td><td>Processed claim ID</td></tr><tr><td>CRU.issuerId</td><td>string</td><td>Issuer identifier</td></tr><tr><td>CRU.processedClaim</td><td>Unknown Type</td><td></td></tr><tr><td>CheckpointResult.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>CheckpointResult.checkpointId</td><td>string</td><td>Checkpoint identifier</td></tr><tr><td>CheckpointResult.linkToVerificationData</td><td>Unknown Type</td><td>Link to verification data</td></tr><tr><td>CheckpointResult.dateRange</td><td>Unknown Type</td><td></td></tr><tr><td>CheckpointResult.efBefore</td><td>string</td><td>Environmental factor before activity</td></tr><tr><td>CheckpointResult.efAfter</td><td>string</td><td>Environmental factor after activity</td></tr><tr><td>CheckpointResult.mrvExtensions</td><td>array</td><td>Collection of MRV extensions</td></tr><tr><td>ClaimSource.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>ClaimSource.aimId</td><td>string</td><td></td></tr><tr><td>ClaimSource.name</td><td>string</td><td>Name of the entity</td></tr><tr><td>ClaimSource.description</td><td>string</td><td>Description of the entity</td></tr><tr><td>ClaimSource.location</td><td>Unknown Type</td><td></td></tr><tr><td>ClaimSource.sourceType</td><td>Unknown Type</td><td>Type of claim source - Sensor, Application, Reference</td></tr><tr><td>ClaimSource.unitOfMeasure</td><td>Unknown Type</td><td>Unit of measurement</td></tr><tr><td>ClaimSource.sourceIdentifier</td><td>string</td><td>Identifier for claim source</td></tr><tr><td>ClaimSource.mrvExtensions</td><td>array</td><td>Collection of MRV extensions</td></tr><tr><td>ClimateLabel.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>ClimateLabel.name</td><td>string</td><td>Name of the entity</td></tr><tr><td>ClimateLabel.description</td><td>string</td><td>Description of the entity</td></tr><tr><td>CoBenefit.unSdg</td><td>Unknown Type</td><td></td></tr><tr><td>CoBenefit.description</td><td>string</td><td>Description of the entity</td></tr><tr><td>CoreCarbonPrinciples.assetId</td><td>string</td><td>Asset identifier</td></tr><tr><td>CoreCarbonPrinciples.issuanceDate</td><td>Unknown Type</td><td>Credit issuance date</td></tr><tr><td>CoreCarbonPrinciples.vintage</td><td>string</td><td>Vintage year of credit</td></tr><tr><td>CoreCarbonPrinciples.generationType</td><td>Unknown Type</td><td>How credit was generated - Actual, Estimated, etc.</td></tr><tr><td>CoreCarbonPrinciples.verificationStandard</td><td>Unknown Type</td><td>Verification standard used</td></tr><tr><td>CoreCarbonPrinciples.mitigationActivity</td><td>Unknown Type</td><td>Mitigation activity details</td></tr><tr><td>CoreCarbonPrinciples.durability</td><td>Unknown Type</td><td></td></tr><tr><td>CoreCarbonPrinciples.replacement</td><td>Unknown Type</td><td></td></tr><tr><td>CoreCarbonPrinciples.parisAgreementCompliance</td><td>Unknown Type</td><td></td></tr><tr><td>CoreCarbonPrinciples.quantifiedSdgImpacts</td><td>array</td><td>Quantified SDG impacts</td></tr><tr><td>CoreCarbonPrinciples.adaptationCoBenefits</td><td>array</td><td>Adaptation co-benefits</td></tr><tr><td>Credential.context</td><td>array</td><td></td></tr><tr><td>Credential.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>Credential.type</td><td>array</td><td></td></tr><tr><td>Credential.issuer</td><td>string</td><td></td></tr><tr><td>Credential.issuanceDate</td><td>string</td><td>Credit issuance date</td></tr><tr><td>Credential.credentialSubject</td><td>Unknown Type</td><td></td></tr><tr><td>Credential.proof</td><td>Unknown Type</td><td></td></tr><tr><td>CredentialSubject.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>CredentialSubject.property</td><td>array</td><td></td></tr><tr><td>DataExtension.key</td><td>string</td><td></td></tr><tr><td>DataExtension.value</td><td>string</td><td></td></tr><tr><td>DataExtension.data</td><td>array</td><td>JSON data for typed extension</td></tr><tr><td>Date.dateTime</td><td>Unknown Type</td><td></td></tr><tr><td>Date.dateString</td><td>string</td><td></td></tr><tr><td>DatePoint.date</td><td>Unknown Type</td><td></td></tr><tr><td>DatePoint.timeStamp</td><td>Unknown Type</td><td></td></tr><tr><td>DateRange.startDate</td><td>Unknown Type</td><td></td></tr><tr><td>DateRange.endDate</td><td>Unknown Type</td><td></td></tr><tr><td>Degradable.percentage</td><td>integer</td><td>Degradation percentage</td></tr><tr><td>Degradable.factor</td><td>integer</td><td>Degradation factor</td></tr><tr><td>Degradable.degradationType</td><td>Unknown Type</td><td>Type of degradation - Linear, Exponential</td></tr><tr><td>DigitalSignature.type</td><td>Unknown Type</td><td></td></tr><tr><td>DigitalSignature.jws</td><td>string</td><td></td></tr><tr><td>DigitalSignature.vc</td><td>Unknown Type</td><td></td></tr><tr><td>DigitalSignature.signatureCase</td><td>Unknown Type</td><td></td></tr><tr><td>Durability.storageType</td><td>Unknown Type</td><td>Storage type - Biological, Geological, etc.</td></tr><tr><td>Durability.years</td><td>integer</td><td>Expected duration in years</td></tr><tr><td>Durability.degradable</td><td>Unknown Type</td><td>Degradability details</td></tr><tr><td>Durability.reversalMitigation</td><td>Unknown Type</td><td></td></tr><tr><td>GeographicLocation.longitude</td><td>string</td><td></td></tr><tr><td>GeographicLocation.latitude</td><td>string</td><td></td></tr><tr><td>GeographicLocation.geoJsonOrKml</td><td>string</td><td></td></tr><tr><td>GeographicLocation.geographicLocationFile</td><td>Unknown Type</td><td></td></tr><tr><td>ImpactClaim.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>ImpactClaim.aimId</td><td>string</td><td></td></tr><tr><td>ImpactClaim.processedClaimId</td><td>string</td><td>Processed claim ID</td></tr><tr><td>ImpactClaim.unit</td><td>Unknown Type</td><td>Unit of credit</td></tr><tr><td>ImpactClaim.quantity</td><td>string</td><td>Quantity of credit</td></tr><tr><td>ImpactClaim.coBenefits</td><td>array</td><td>Collection of co-benefits</td></tr><tr><td>ImpactClaim.checkpoints</td><td>array</td><td>Collection of checkpoints</td></tr><tr><td>ImpactClaim.mrvExtensions</td><td>array</td><td>Collection of MRV extensions</td></tr><tr><td>ImpactClaim.activityImpactModule</td><td>Unknown Type</td><td></td></tr><tr><td>ImpactClaimCheckpoint.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>ImpactClaimCheckpoint.claimId</td><td>string</td><td></td></tr><tr><td>ImpactClaimCheckpoint.claimSourceIds</td><td>array</td><td></td></tr><tr><td>ImpactClaimCheckpoint.projectDeveloperId</td><td>string</td><td></td></tr><tr><td>ImpactClaimCheckpoint.efBefore</td><td>string</td><td>Environmental factor before activity</td></tr><tr><td>ImpactClaimCheckpoint.efAfter</td><td>string</td><td>Environmental factor after activity</td></tr><tr><td>ImpactClaimCheckpoint.checkpointDateRange</td><td>Unknown Type</td><td>Checkpoint date range</td></tr><tr><td>ImpactClaimCheckpoint.verifiedLinkToCheckpointData</td><td>Unknown Type</td><td>Link to checkpoint data</td></tr><tr><td>ImpactClaimCheckpoint.mrvExtensions</td><td>array</td><td>Collection of MRV extensions</td></tr><tr><td>ImpactClaimCheckpoint.spanDataPackage</td><td>Unknown Type</td><td></td></tr><tr><td>MRVRequirements.measurementSpecification</td><td>Unknown Type</td><td></td></tr><tr><td>MRVRequirements.specificationLink</td><td>Unknown Type</td><td></td></tr><tr><td>MRVRequirements.precision</td><td>Unknown Type</td><td></td></tr><tr><td>MRVRequirements.claimPeriod</td><td>Unknown Type</td><td></td></tr><tr><td>Manifest.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>Manifest.version</td><td>string</td><td></td></tr><tr><td>Manifest.aimId</td><td>string</td><td></td></tr><tr><td>Manifest.claimId</td><td>string</td><td></td></tr><tr><td>Manifest.projectDeveloperId</td><td>string</td><td></td></tr><tr><td>Manifest.created</td><td>Unknown Type</td><td></td></tr><tr><td>Manifest.mrvExtensions</td><td>array</td><td>Collection of MRV extensions</td></tr><tr><td>Manifest.sdpFiles</td><td>array</td><td>Collection of SDP files</td></tr><tr><td>MitigationActivity.category</td><td>Unknown Type</td><td></td></tr><tr><td>MitigationActivity.method</td><td>Unknown Type</td><td></td></tr><tr><td>MrvExtension.mrvExtensionContext</td><td>Unknown Type</td><td>Context for MRV extension - AIM, Claim, etc.</td></tr><tr><td>MrvExtension.typedExtension</td><td>Unknown Type</td><td>Typed MRV extension</td></tr><tr><td>MrvExtension.untypedExtension</td><td>Unknown Type</td><td>Untyped MRV extension</td></tr><tr><td>MrvExtension.extensionCase</td><td>Unknown Type</td><td></td></tr><tr><td>PACompliance.ca</td><td>Unknown Type</td><td></td></tr><tr><td>PACompliance.letterOfApproval</td><td>Unknown Type</td><td>Link to approval letter</td></tr><tr><td>PrecisionMix.low</td><td>integer</td><td></td></tr><tr><td>PrecisionMix.medium</td><td>integer</td><td></td></tr><tr><td>PrecisionMix.high</td><td>integer</td><td></td></tr><tr><td>ProcessedClaim.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>ProcessedClaim.vpaId</td><td>string</td><td></td></tr><tr><td>ProcessedClaim.impactClaimId</td><td>string</td><td></td></tr><tr><td>ProcessedClaim.creditId</td><td>string</td><td>Credit identifier</td></tr><tr><td>ProcessedClaim.unit</td><td>Unknown Type</td><td>Unit of credit</td></tr><tr><td>ProcessedClaim.quantity</td><td>string</td><td>Quantity of credit</td></tr><tr><td>ProcessedClaim.coBenefits</td><td>array</td><td>Collection of co-benefits</td></tr><tr><td>ProcessedClaim.mrvExtensions</td><td>array</td><td>Collection of MRV extensions</td></tr><tr><td>ProcessedClaim.checkpointResults</td><td>array</td><td>Collection of checkpoint results</td></tr><tr><td>ProcessedClaim.issuanceRequest</td><td>Unknown Type</td><td></td></tr><tr><td>ProcessedClaim.verificationProcessAgreement</td><td>Unknown Type</td><td></td></tr><tr><td>ProcessedClaim.impactClaim</td><td>Unknown Type</td><td></td></tr><tr><td>ProcessedClaim.asset</td><td>Unknown Type</td><td></td></tr><tr><td>Proof.type</td><td>Unknown Type</td><td></td></tr><tr><td>Proof.created</td><td>string</td><td></td></tr><tr><td>Proof.proofPurpose</td><td>string</td><td></td></tr><tr><td>Proof.verificationMethod</td><td>string</td><td></td></tr><tr><td>Proof.challenge</td><td>string</td><td></td></tr><tr><td>Proof.domain</td><td>string</td><td></td></tr><tr><td>Proof.jws</td><td>string</td><td></td></tr><tr><td>QualityStandard.name</td><td>string</td><td>Name of the entity</td></tr><tr><td>QualityStandard.description</td><td>string</td><td>Description of the entity</td></tr><tr><td>QualityStandard.standard</td><td>Unknown Type</td><td></td></tr><tr><td>QualityStandard.methodologyAndTools</td><td>array</td><td></td></tr><tr><td>QualityStandard.version</td><td>string</td><td></td></tr><tr><td>QualityStandard.coBenefits</td><td>array</td><td>Collection of co-benefits</td></tr><tr><td>QualityStandard.standardLink</td><td>Unknown Type</td><td></td></tr><tr><td>REC.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>REC.recType</td><td>Unknown Type</td><td>REC type - IREC, NERC</td></tr><tr><td>REC.validJurisdiction</td><td>string</td><td>Valid jurisdiction for REC</td></tr><tr><td>REC.quantity</td><td>string</td><td>Quantity of credit</td></tr><tr><td>REC.unit</td><td>Unknown Type</td><td>Unit of credit</td></tr><tr><td>REC.ownerId</td><td>string</td><td></td></tr><tr><td>REC.listingAgentId</td><td>string</td><td></td></tr><tr><td>REC.climateLabels</td><td>array</td><td>Collection of climate labels</td></tr><tr><td>REC.status</td><td>Unknown Type</td><td>Status of credit - Active, Inactive, etc.</td></tr><tr><td>REC.referencedRec</td><td>Unknown Type</td><td></td></tr><tr><td>REC.appliedToId</td><td>string</td><td>Identifier credit was applied to</td></tr><tr><td>REC.processedClaimId</td><td>string</td><td>Processed claim ID</td></tr><tr><td>REC.issuerId</td><td>string</td><td>Issuer identifier</td></tr><tr><td>REC.processedClaim</td><td>Unknown Type</td><td></td></tr><tr><td>ReferencedCredit.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>ReferencedRec.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>Replacement.replacesId</td><td>string</td><td></td></tr><tr><td>Replacement.replacementDate</td><td>Unknown Type</td><td>Date credit was replaced</td></tr><tr><td>Replacement.notes</td><td>string</td><td></td></tr><tr><td>ReversalMitigation.reversalRisk</td><td>Unknown Type</td><td>Risk of reversal - Zero, Low, Material</td></tr><tr><td>ReversalMitigation.insuranceType</td><td>Unknown Type</td><td>Insurance type - Buffer Pool, Refund, etc.</td></tr><tr><td>ReversalMitigation.insurancePolicyOwner</td><td>Unknown Type</td><td>Owner of insurance policy</td></tr><tr><td>ReversalMitigation.insurancePolicyLink</td><td>Unknown Type</td><td>Link to insurance policy</td></tr><tr><td>SdpFile.name</td><td>string</td><td>Name of the entity</td></tr><tr><td>SdpFile.type</td><td>Unknown Type</td><td></td></tr><tr><td>SdpFile.description</td><td>string</td><td>Description of the entity</td></tr><tr><td>SdpFile.claimSourceId</td><td>string</td><td>Claim source ID</td></tr><tr><td>SdpFile.claimSourceAttestation</td><td>string</td><td>Claim source attestation</td></tr><tr><td>SdpFile.mrvExtensions</td><td>array</td><td>Collection of MRV extensions</td></tr><tr><td>Signatory.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>Signatory.name</td><td>string</td><td>Name of the entity</td></tr><tr><td>Signatory.description</td><td>string</td><td>Description of the entity</td></tr><tr><td>Signatory.signatoryRole</td><td>enum</td><td>"IssuingRegistry",<br>"ValidationAndVerificationBody",<br>"ProjectOwner",<br>"VerificationPlatformProvider"</td></tr><tr><td>Signatory.signature</td><td>Unknown Type</td><td></td></tr><tr><td>SpanDataPackage.manifest</td><td>Unknown Type</td><td>Manifest for span data package</td></tr><tr><td>Tag.name</td><td>string</td><td>Name of the entity</td></tr><tr><td>Tag.context</td><td>array</td><td></td></tr><tr><td>Tag.description</td><td>string</td><td>Description of the entity</td></tr><tr><td>Tag.data</td><td>string</td><td>JSON data for typed extension</td></tr><tr><td>Timestamp.seconds</td><td>integer</td><td></td></tr><tr><td>Timestamp.nanos</td><td>integer</td><td></td></tr><tr><td>TypedExtension.dataSchema</td><td>string</td><td>Schema URL for typed extension</td></tr><tr><td>TypedExtension.documentation</td><td>string</td><td>Documentation URL for extension</td></tr><tr><td>TypedExtension.data</td><td>string</td><td>JSON data for typed extension</td></tr><tr><td>UntypedExtension.name</td><td>string</td><td>Name of the entity</td></tr><tr><td>UntypedExtension.version</td><td>string</td><td></td></tr><tr><td>UntypedExtension.description</td><td>string</td><td>Description of the entity</td></tr><tr><td>UntypedExtension.documentation</td><td>string</td><td>Documentation URL for extension</td></tr><tr><td>UntypedExtension.dataExtensions</td><td>array</td><td></td></tr><tr><td>Validation.validationDate</td><td>Unknown Type</td><td>Validation date</td></tr><tr><td>Validation.validatingPartyId</td><td>string</td><td>Validating party ID</td></tr><tr><td>Validation.validationMethod</td><td>string</td><td>Validation method used</td></tr><tr><td>Validation.validationExpirationDate</td><td>Unknown Type</td><td>Validation expiration date</td></tr><tr><td>Validation.validationSteps</td><td>array</td><td>Collection of validation steps</td></tr><tr><td>ValidationStep.validationStepName</td><td>string</td><td>Name of validation step</td></tr><tr><td>ValidationStep.validationStepDescription</td><td>string</td><td>Description of validation step</td></tr><tr><td>ValidationStep.validationStepStatus</td><td>Unknown Type</td><td>Status of validation step - Not Started, In Progress, Completed</td></tr><tr><td>ValidationStep.validationStepDocumentLink</td><td>Unknown Type</td><td></td></tr><tr><td>VerificationProcessAgreement.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>VerificationProcessAgreement.name</td><td>string</td><td>Name of the entity</td></tr><tr><td>VerificationProcessAgreement.description</td><td>string</td><td>Description of the entity</td></tr><tr><td>VerificationProcessAgreement.signatories</td><td>array</td><td>Collection of agreement signatories</td></tr><tr><td>VerificationProcessAgreement.qualityStandard</td><td>Unknown Type</td><td>Quality standard used</td></tr><tr><td>VerificationProcessAgreement.mrvRequirements</td><td>Unknown Type</td><td>MRV requirements</td></tr><tr><td>VerificationProcessAgreement.agreementDate</td><td>Unknown Type</td><td></td></tr><tr><td>VerificationProcessAgreement.estimatedAnnualCredits</td><td>string</td><td>Estimated annual credits</td></tr><tr><td>VerificationProcessAgreement.aimId</td><td>string</td><td></td></tr><tr><td>VerificationProcessAgreement.auditSchedule</td><td>Unknown Type</td><td>Audit schedule - Annual, Biannual, etc.</td></tr><tr><td>VerificationProcessAgreement.audits</td><td>Unknown Type</td><td>Audit details</td></tr><tr><td>VerificationProcessAgreement.activityImpactModule</td><td>Unknown Type</td><td></td></tr><tr><td>VerificationProcessAgreement.processedClaims</td><td>array</td><td></td></tr><tr><td>VerifiedLink.id</td><td>string</td><td>Unique identifier</td></tr><tr><td>VerifiedLink.uri</td><td>string</td><td></td></tr><tr><td>VerifiedLink.description</td><td>string</td><td>Description of the entity</td></tr><tr><td>VerifiedLink.hashProof</td><td>string</td><td></td></tr><tr><td>VerifiedLink.hashAlgorithm</td><td>Unknown Type</td><td></td></tr></tbody></table>


# Schema Design Best Practices

Best practices for implementing the schema cycle in Hedera Guardian involve a systematic approach to schema design, development, testing, deployment, versioning, and ongoing iteration as part of the complete methodology digitization lifecycle.

### Schema Cycle Best Practices

* **Excel-First Design**: Begin schema development using detailed Excel templates to map parameters, field types, defaults, validation rules, and conditional logic. This facilitates collaboration and clarity before importing into Guardian.
* **Incremental Development**: Follow a logical sequence—start with foundational schema architecture, progress to detailed project description (PDD) schemas, then monitoring/reporting schemas, followed by advanced techniques such as API-driven updates and UUID management.
* **Testing and Validation**: Make sure to include default, suggested, and test values into your schemas wherever possible. Use them for practical testing, to verify logical constraints and user experience utilizing Guardian’s testing features before publishing.
* **Version Control and Migration**: Manage schema versions carefully with semantic versioning, maintain backward compatibility when possible, and follow planned migration paths to newer versions with deprecation notices.
* **Conditional and Visibility Logic**: Implement conditional sub-schemas and field visibility toggles to streamline user input flows and accommodate complex project workflows dynamically.
* **Reusability and Modularity**: Design schemas to be reusable components across multiple policies and methodologies to encourage standardization and reduce duplication.
* **Documentation and Metadata**: Maintain detailed documentation within and alongside schemas to provide context, field definitions, use cases, and change history for stakeholders.

Related

* [Creating Policies](https://www.youtube.com/watch?v=AAlu1btvkGc\&list=PLnld0e1pwLhqdR0F9dusqILDww6uZywwR\&index=4) (Youtube)


# Excel-First Design

Detailed best practices for Excel-first design in building Hedera Guardian schemas focus on using structured Excel templates to define all necessary fields, data types, validation rules, and conditional logic clearly before importing into Guardian. This method improves collaboration, clarity, and iterative feedback especially for complex sustainability methodologies.

### Key Best Practices for Excel-First Design

* **Start with a Standard Header**\
  Use the first rows of the Excel sheet to define the schema identity and type, e.g.,

  * Row 1: Schema Name (e.g., "Project Description (Auto)")
  * Row 2: Schema Description
  * Row 3: Schema Type (e.g., "Verifiable Credentials")
  * Row 4: Column headings for schema field attributes (Required Field, Field Type, Parameter, Visibility, Description, Allow Multiple Answers, Test Value, Default Value, Suggest Value, Key).

  <figure><img src="/files/WirvzFdQQ40MA5HFQVKC" alt=""><figcaption></figcaption></figure>
* **Define Each Field with Clear Attributes**\
  For every schema field, specify:

  * Required (Yes/No)
  * Field Type (String, Number, Date, Enum, Boolean, Image, Auto-Calculate, Help Text, etc.)
  * Parameter or reference to enums/calculations if applicable
  * Visibility setting (TRUE/FALSE/Hidden) to control when fields appear
  * User-facing question (label text)
  * Allow multiple answers? (Yes/No)
  * Default or example value for user guidance.

  <figure><img src="/files/NrXBiZGPLJ4jEEIkFvK5" alt=""><figcaption></figcaption></figure>
* **Use a Shared Enum Tab for Controlled Vocabularies**\
  All enumerated types are defined in a single shared `Enums` tab with four columns: Schema name, Field name, Loaded to IPFS, Value. Group values by field, fill in Schema name, Field name, and Loaded to IPFS only on the first row of each group, leaving them blank for subsequent values.

<figure><img src="/files/F7cGkFqNlPrSdOMS6vD7" alt=""><figcaption></figcaption></figure>

* **Define Sub-Schemas Inline**\
  Fields of type `Sub-Schema` group nested child fields directly.
* **Implement Conditional Logic via Visibility Columns**\
  Use TRUE to keep fields always visible; use FALSE or "Hidden" to permanently hide fields (e.g., system-only or metadata fields); use a formula (EXACT, OR, AND) in the Visibility column for conditional visibility based on enum selections or workflow stage. This reduces user burden and aligns forms dynamically with project selections.

<figure><img src="/files/CxWHBidJNN0w3m11We2A" alt=""><figcaption></figcaption></figure>

* **Incorporate Advanced Field Types**\
  Include Auto-Calculate fields for computed values, Image/File Upload fields for supporting documents, and Help Text fields to provide contextual guidance inline.

<figure><img src="/files/0Ch59NWT6l4n27kSIobM" alt=""><figcaption></figcaption></figure>

* **Validation and Data Integrity**\
  Mark critical fields as required to enforce data capture. Choose proper data types for automatic Guardian validation (numbers, dates, boolean, urls). Use patterns or formulas as needed for more complex rules.
* **Field Key Management Post-Import**\
  After importing, rename default field keys in Guardian UI to meaningful, calculation-friendly names. This dramatically improves maintainability of formula/code logic referencing schema fields.
* **Collaborate Closely with Domain Experts**\
  Excel-first enables domain experts (e.g., carbon scientists) to review, comment, and iterate schema designs before committing to implementation.


# Incremental Development

Best practices for incremental development of schemas in Hedera Guardian emphasize building schemas in logical, manageable stages that align with methodology complexity and user needs. The approach ensures rapid iteration, better error handling, and scalable schema growth.

### Key Best Practices for Incremental Development

* **Start with Schema Architecture Foundations**\
  Begin by developing foundational schema components that define the basic building blocks and data types used across the methodology. Typical first step: a core Project Description schema capturing essential metadata and identifiers.
* **Develop Project Design Document (PDD) Schemas Step-by-Step**\
  Add detailed fields incrementally, focusing on critical project attributes first (titles, locations, timeframes). Then introduce conditional logic and sub-schemas to handle complex branching scenarios, e.g., certification pathways or multiple modalities.
* **Build Monitoring and Reporting Schemas Separately**\
  Once PDD schemas are stable, incrementally add monitoring-report schemas that handle time-series data, quality control parameters, and validation evidence. This separation helps manage temporal data complexities and VVB verification workflows.
* **Use Excel-First Design for Collaboration and Clarity**\
  Define schema additions in Excel sheets before import, allowing team reviews and feedback at each stage, reducing rework and enhancing shared understanding.
* **Employ Semantic Versioning**\
  Increment versions for every schema update, marking breaking changes distinctly. This helps track schema history and supports backward compatibility checks.
* **Test Frequently at Each Increment**\
  Validate each schema addition in Guardian’s testing environment using a mix of default and edge-case test data. Fix validation gaps, refine user experience, and verify all conditional logic before proceeding.
* **Manage Field Key Naming Consistently**\
  Assign meaningful, calculation-friendly field keys early and maintain consistency across increments to simplify later code maintenance and formula writing.
* **Incorporate Advanced Features Last**\
  After core and monitoring schemas are stable, introduce advanced functions like API schema management, auto-calculated fields, UUID management, and integration with policy workflows.
* **Document Incremental Changes Clearly**\
  Maintain change logs to communicate additions, removals, or modifications in each schema version to stakeholders and downstream systems.


# Testing and Validation

Best practices for testing and validation of schemas in Hedera Guardian focus on using Guardian’s built-in testing tools, structured validation rule configuration, and systematic pre-deployment checks to ensure data integrity and a smooth user experience.

### Key Best Practices for Testing and Validation

* **Use a Layered Testing Approach**\
  Test schemas with multiple types of data inputs including:
  * Default Values: Prepopulated values to verify logic and defaults
  * Suggested Values: Sample inputs for user guidance
  * Test Values: Edge cases and real-world scenarios to stress-test validation rules.
* **Validation Rule Configuration**\
  Define explicit validation rules for each field, including:
  * Required field enforcement
  * Value ranges for numeric fields (e.g., latitude must fall between -90 and 90)
  * Enum value restrictions for controlled vocabularies
  * Patterns or formats for strings (e.g., URLs, date formatting)
  * Conditional validation depending on other field values, ensuring context-appropriate data capture.
* **Preview and Simulation**\
  Utilize Guardian’s schema preview mode to simulate user input and workflow transitions before publishing. Confirm that conditional visibility, sub-schema activation, and validation messages behave as expected.
* **Test UUID Integration and Policy Workflow Compatibility**\
  Confirm that UUID field keys are correctly managed and that schema data cleanly integrates with policy workflows and credential issuance processes.
* **Logical Field Organization**\
  Group related fields logically to simplify validation and to facilitate formula application for calculated fields. This organization supports comprehensive, maintainable schema validation.
* **Document Test Cases and Results**\
  Maintain records of validation test cases, pass/fail outcomes, and corrective actions. This documentation supports audit readiness and ongoing maintenance.
* **User Experience (UX) Focus**\
  Confirm validation error messages are clear, actionable, and guide users efficiently to resolve issues during data submission.
* **Iterative Refinement**\
  Use feedback from testing and real-world use to iteratively improve schema validation rules and data capture quality.


# Version Control and Migration

Best practices for version control and migration in Hedera Guardian schemas center on maintaining backward compatibility, clear semantic versioning, planned deprecation, and thorough documentation to ensure smooth transitions across schema updates.

### Version Control Best Practices

* **Semantic Versioning**\
  Use a major.minor.micro format for schema versioning:
  * **Micro**: Non-breaking minor edits (descriptive changes, comments)\
    This convention helps users recognize change impact at a glance and plan accordingly.
  * **Minor**: Non-breaking but notable changes (adding new fields, new enum values, adjusting required/optional status)
  * **Major**: Breaking changes (removing, renaming, or altering field types)
* **Preserve Backward Compatibility**\
  Avoid removing or modifying existing schema elements. Instead, add new fields or enums for new functionality so older schemas remain valid and usable by the Guardian Policy Engine indefinitely.
* **Deprecation Notice and Grace Period**\
  When a schema version or element is deprecated, provide a minimum 2-month notice through metadata annotations and official release notes. Communicate end-of-life dates and issue revocation notices on Hedera Topics at expiry for transparency.
* **Maintain Schema Registry and Metadata**\
  Document all versions, status (active, deprecated, unsupported), and compatibility information in a centralized registry. This facilitates tracking and migration planning.

### Migration Best Practices

* **Versioned Migrations with Clear Documentation**\
  Maintain detailed change logs describing all schema modifications, reasons for change, and migration guides to assist consumers in adapting to newer schema versions.
* **Testing Migration Paths**\
  Thoroughly test backward and forward compatibility of schemas during upgrades using controlled test data and simulations within Guardian.
* **Plan for Obsolete Elements**\
  Prepare tools and processes to phase out obsolete schema elements by removing them from newly created schemas and guiding users on alternate fields.
* **Align Schema Versioning with Policy Engine Releases**\
  Sync schema language changes with Guardian engine updates to manage technological dependencies and leverage new platform capabilities effectively


# Conditional and Visibility Logic

Best practices for implementing conditional and visibility logic in Hedera Guardian schemas focus on maintaining clarity, avoiding conflicts, and ensuring logical coherence across user input flows. Effective use of these practices ensures schemas adapt dynamically to user interactions while remaining maintainable and robust.

### Key Best Practices

* **Visualize User Workflow First**\
  Map out scenarios and user journeys before defining conditional logic. This helps identify where fields should appear, be hidden, required, or read-only depending on prior inputs, ensuring an intuitive form flow.

<figure><img src="/files/r5V2z0bJSzmMif2xN3NQ" alt=""><figcaption></figcaption></figure>

* **Use Clear and Distinct Conditions**\
  Define precise conditional statements that combine multiple criteria sensibly. For example, use AND/OR logic to activate visibility rules rather than relying on overlapping or ambiguous conditions, preventing conflicts when multiple rules could apply.
* **Avoid Overly Complex Nesting**\
  Instead of stacking multiple nested if-then-else statements, leverage `oneOf` or `anyOf` constructs where possible, which simplifies schema readability and validation performance. This approach is especially useful for multiple mutually exclusive states.
* **Combine Conditions When Necessary**\
  For complex workflows, combine multiple conditions into a single rule rather than having separate rules that could override each other. For example, structure combined conditions as:\
  IF (Q1 = "Yes" AND Q2 >= 3) THEN show Q3 else hide Q3.\
  This prevents conflicts where last-interaction rules could unintentionally override previous ones.

<figure><img src="/files/tI45100oqIlh5speGsYp" alt=""><figcaption></figcaption></figure>

* **Test Conditional Logic Extensively**\
  Rigorous testing is essential. Use Guardian’s dry run mode or real data simulations to verify that fields behave as expected across all relevant input combinations. Confirm that visibility and requirement rules are mutually consistent.

<figure><img src="/files/nWG8dpA22KdC2khk25SX" alt=""><figcaption></figcaption></figure>

* **Explicitly Label Rules and Conditions**\
  Clearly describe each conditional rule’s purpose with labels and comments. This documentation helps team members understand reasoning, especially when rules grow complex.

<figure><img src="/files/oWeluKUuNnVoVMtq4Rj3" alt=""><figcaption></figcaption></figure>

* **Handle Overwrites Carefully**\
  Be mindful that rules can override each other. Explicitly document and test cases where multiple conditions influence the same field to ensure consistent behavior. When conflicts arise, merge conditions into a single, comprehensive rule.
* **Use Standardized Syntax and Functions**\
  If the schema platform supports it, employ functions and operators like `allOf`, `anyOf`, `not`, and `if-then-else` for clarity and efficiency.

### Example Approach

Instead of overlapping rules:

* Rule 1: IF Q1 = "Yes" THEN Q2 visible
* Rule 2: IF Q3 < 5 THEN Q2 not visible

Use:

* IF (Q1 = "Yes" AND Q3 >= 5) THEN Q2 visible, ELSE hidden.

This way, a single, comprehensive rule governs the visibility, avoiding conflicts.


# Reusability and Modularity

Best practices for reusability and modularity in Hedera Guardian schemas focus on designing schemas and modules that are independent, focused, and easily composable, enabling efficient management and scaling of sustainability projects.

### Reusability Best Practices

* **Define Standardized, General-Purpose Schemas**\
  Create schemas that can be used across multiple methodologies and policies, e.g., Emission Reduction Schema, Project Description Schema. Promote standard field definitions and controlled vocabularies for interoperability.
* **Avoid Redundancy**\
  Use shared schemas whenever possible rather than duplicating similar data structures in multiple places. This reduces maintenance overhead and ensures consistency across projects and registries.
* **Parameterize for Flexibility**\
  Design schemas with configurable fields (enums, optional fields) that allow customization by projects without requiring new schema definitions, enabling broad applicability and adaptation.
* **Version and Document Carefully**\
  Provide clear versioning and documentation so users understand schema capabilities and when to upgrade or extend them for specific project needs.

### Modularity Best Practices

* **Single Responsibility Principle**\
  Each schema or module should focus on a single concept or data entity (e.g., project metadata, monitoring report, verification document). This enhances clarity and maintainability.
* **Encapsulate Functionality**\
  Group related fields and logic into distinct schema modules that can be reused or replaced independently without impacting the entire ecosystem.
* **Low Coupling, High Cohesion**\
  Minimize dependencies between modules so changes in one do not ripple across others. Use well-defined interfaces (field keys, enums) to connect modules cleanly.
* **Organize Code and Schema Files Logically**\
  Structure schema repository or project directories by logical modules, simplifying navigation, updates, and testing.
* **Write Unit Tests for Modules**\
  Test schema modules independently to ensure their correctness and facilitate safe reuse.


# Documentation and Metadata

Best practices for documentation and metadata in Hedera Guardian schemas emphasize clarity, completeness, standardization, and version control to ensure maintainability, interoperability, and trust across the sustainability ecosystem.

### Key Best Practices

* **Clear Schema Purpose and Scope**\
  Document the schema name, version, and a concise description of its purpose and intended use. This helps all participants understand the context and application of the schema at a glance.
* **Field-Level Documentation**\
  Provide descriptive labels and user-facing questions for every field. Include guidance notes or help text where needed to clarify expected input and reduce data entry errors.
* **Standardized Data Model Annotation**\
  Define data types, required status, allowed values (e.g., enums), validation rules, and relationships explicitly in metadata. This supports machine readability and enforces data integrity before on-chain issuance.
* **Version History and Change Log**\
  Maintain detailed versioning metadata including semantic version number, release date, author, and change summary. Track additions, removals, and modifications between versions for auditability and migration planning.
* **Schema Metadata Fields**\
  Include metadata fields for:
  * **Author/Owner**: Responsible party for the schema
  * **Date Created/Updated**: Timestamps for lifecycle tracking
  * **Deprecation Status**: Flags and notes if the schema or parts are deprecated
  * **External References**: Links to related policies, methodologies, or standards.
* **Use Structured Formats**\
  Maintain documentation alongside JSON schema definitions or Excel templates in human-readable formats supplemented by machine-readable annotations embedded in the schema where supported.
* **Interlink Schemas and Modules**\
  Reference related schemas or modules explicitly within metadata to indicate composability and relationships, improving navigation and reuse.
* **Stakeholder Accessibility**\
  Store documentation and metadata in accessible, version-controlled repositories, ensuring all stakeholders (developers, auditors, validators, regulators) have up-to-date schema information.
* **Audit Trail and Transparency**\
  Leverage Guardian’s trust chain to log schema publications, updates, and deprecation, providing a verifiable provenance record for regulatory and community trust.
* **Training and Examples**\
  Supplement schema documentation with usage examples, test data, and training materials to facilitate adoption and proper implementation.


# Creating a Schema

#### **1. Log in as a Standard Registry**

* Only a **Standard Registry (SR)** role can create schemas.
* Sign in to Guardian with your SR account.

#### **2. Navigate to the Schema Section**

* From the left-hand navigation panel, go to **Manage** **Schemas**.
* You’ll see system schemas (default ones) and any custom schemas already created.

<figure><img src="/files/pOUHhyrwHoeGJCzN4FEi" alt=""><figcaption></figcaption></figure>

#### **3. Create a New Schema**

* Click **“Create Schema”**.
* Provide basic details:
  * **Name** → e.g., *Project Registration Schema*
  * **Policy** → Linking the policy e.g., VM0042 V2.1
  * **Description** → short explanation of what the schema will be used for
  * For(Entity) → Select the relevant document.

<figure><img src="/files/EogmWTVBGoKuASZ6nWfL" alt=""><figcaption></figcaption></figure>

#### **4. Define Schema Fields**

* Add **attributes (fields)** that define the data structure. For each field, you specify:
  * **Field Name** (e.g., *projectId*, *location*, *CO2Reduced*)
  * **Property** (property referring to schema field)
  * **Field Type** (string, number, boolean, array, object, date, etc.)
  * **Required or Optional**
  * **Allow multiple answers checkbox**
  * **Selected values (adding default, suggested, test values)**
* Example fields for a Project Schema:
  * `projectId` → number (required)

<figure><img src="/files/PT3rMpwyXycGYeQCL3Lp" alt=""><figcaption></figcaption></figure>

We can also customize the Field keys and Field Title by clicking on Advanced Tab.

<figure><img src="/files/MHcC57EuTtOyFVRRGQYE" alt=""><figcaption></figcaption></figure>

Schemas can be defined/changed by editing their JSON definitions

<figure><img src="/files/1mwi1UrKp4GBeVvePZoK" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/GMLbrj3wLFitHeZKkSat" alt=""><figcaption></figcaption></figure>

Schema JSON definition contains the following editable fields

1. **name** – schema name
2. **description** – schema description
3. **entity** – schema type (NONE, VC, EVC)
4. **fields** – schema fields array
   1. **key** – key (name) of the field
   2. **title** – field title
   3. **description** – schema description (visible to the user)
   4. **required** – field visibility/type (Auto Calculate, Hidden, Required, None)
   5. **type** – field value type (Number, String, Enum, …) or the sub-schema reference (#be764ef6-…)
   6. **isArray** – boolean field (true\false) determining whether the field is an array
   7. **property** – optional field mapping onto the corresponding property from dMRV framework (<https://interworkalliance.github.io/TokenTaxonomyFramework/dmrv/spec/>)
   8. **private** – if the field is private (only relevant for ‘selective disclosure’ EVCs)
   9. **enum** – array of options, or reference to an array of options
   10. **textSize** – size of the text (only for Help Text)
   11. **textColor** – color of the text (only for Help Text)
   12. **textBold** – if the text is bold (only for Help Text)
   13. **pattern** – regular expression to format the inputted text (only relevant for Strings)
   14. **expression** – formula for calculating field values (only for ‘Auto Calculate’ fields)
   15. **unit** – fixed Prefix or Postfix (only for Prefix or Postfix)
   16. **example** – example values for the field
   17. **default** – default value for the field
   18. **suggest** – suggested value for the field
5. **conditions** – schema name
   1. **if** – conditions for displaying the fields (only equality is supported)
      1. **field** – key (name) of the field
      2. **value** – comparison value for the field value
   2. **then** – array of fields which is shown when the condition resolves to true (the same format as *fields*)
   3. **else** – array of fields which is shown when the condition resolves to false (the same format as *fields*)
   4. **IF OR** – at least one rule must be met, and you can add unlimited fields
   5. **IF AND** – all rules must be met, and you can add unlimited fields

<figure><img src="/files/qt7TLOR4vEdR7y2csgFP" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/8tfmUryLlyl7tvHTeuaR" alt=""><figcaption></figcaption></figure>

**5. Save & Publish the Schema**

* Once all fields are defined → click **Save**.
* To make it usable in policies, click **Publish**.
  * Publishing makes the schema immutable and available to others.

<figure><img src="/files/jXJUnRY38pI7v8nCS6cv" alt=""><figcaption></figcaption></figure>

6. **Version**

After clicking on Publish, you will be prompted to enter the version. After entering the Version and pressing the submit button, the status will change to Published.

<figure><img src="/files/jrrY21uK2veT82i1xKJ4" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
**Note**: All Schemas connected to a Policy gets published automatically when Policy gets published.
{% endhint %}

Once the System Schema is created, we have options for activating, deleting, editing and viewing JSON documents.

![](/files/GzQQVBCBGfttH4NC7SBe)


# Deleting a Schema

## 1. Overview

When a user attempts to delete a schema from the grid page, a modal window appears to confirm the action and display relevant dependency information.

<figure><img src="/files/60AyjRaBia2Y0Cl8uHpX" alt=""><figcaption></figcaption></figure>

## 2. Functional Details

### 2.1 Deleting Schemas with Child Schemas

When deleting a schema that has child schemas:

* The modal displays a list of all child schemas that can be deleted along with it.
* It also shows which child schemas cannot be deleted due to dependencies on other schemas.
* A checkbox allows the user to choose whether to:
* Delete only the selected schema, or
* Delete the selected scheme and all its child schemas.

<figure><img src="/files/6FiPCAx3eyiHT5E9yFfk" alt=""><figcaption></figcaption></figure>

### 2.2 Deleting Schemas with Parent Dependencies

If the selected schema depends on one or more parent schemas, deletion is not allowed.\
In this case:

* The modal displays a warning message explaining that the scheme cannot be deleted due to existing dependencies.

<figure><img src="/files/juhTeEk4hgjDx2qM0fpr" alt=""><figcaption></figcaption></figure>

### 2.3 Deleting all Schemas

User will now be able to delete all schemas for a particular policy by using "Delete All Schemas" button:

<figure><img src="/files/BIx49VDnH1CcjrOFKzEI" alt=""><figcaption></figcaption></figure>

### 2.4 Delete Multiple Schemas

Added ability to select and delete items from schema table in Guardian UI.

<figure><img src="/files/kFVUyh2sZb5yX5vAc9Bz" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Note:

1. Selected items remain selection across pagination.
2. Dependencies are considered when deleting multiple schemas.
   {% endhint %}


# Importing a Schema

#### **1. Log in as Standard Registry**

* Only a **Standard Registry (SR)** can import schemas.
* Sign in to Guardian with your SR account.

#### **2. Go to the Schema Section**

* From the left navigation panel, click **Manage** **Schemas**.
* You’ll see a list of **System Schemas** (default ones) and any **Custom Schemas** created.

#### **3. Select “Import Schema”**

* Click the **Import Schema** button (usually in the top-right corner).

<figure><img src="/files/kAdCfYx6NZ84nQKhyvrL" alt=""><figcaption></figcaption></figure>

#### **4. Choose Import Source**

Guardian allows multiple ways to import schemas:

1. **From File (.json)**
   * Select Upload File.
   * Browse and upload a schema JSON file (must follow JSON Schema format).
2. **From IPFS / DID / URL**
   * Paste the schema IPFS CID, DID reference, or a public URL.
   * Guardian fetches the schema definition from that source.
3. **From Excel**
   * Select .xl file.
   * Browse and upload excel file.

<figure><img src="/files/C8xhNLrMGeoe7xhTvurs" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Note:

1. Files with **.schema** extension are only accepted. These files are in zip format, i.e. they are zip archives of the text file.
2. Initially when the Schema is created/imported, it will be in draft status.
   {% endhint %}


# Schema Versioning & Deprecation Policy

This policy comes into effect beginning with Guardian 1.3.0

Guardian schema documents specify the content of Verifiable Credentials (VCs) and Verifiable Presentations (VP), which are produced by the Policy Workflow Engine in accordance with the configuration of the specific policy being executed. Effectively, schemas define the input/output ‘data’ part of policy execution, and therefore are constituent part of policy definition. The driving forces for the evolution of policies fully apply to schemas, namely:

* The evolution of the sustainability industry use-case targeted by the policy in question.
* Introduction of new use-cases and corresponding policies.
* The evolution of Guardian Policy Engine technology, where new capabilities are added existing modified or removed.

Additionally, building blocks of Guardian schema definition language, e.g. types and other content, must conform to W3C and JSON-LD specifications and as such evolve on a separate schedule. These may require changes in the vocabulary and semantics independently of the driving forces highlighted above.

These processes result in the following changes:

* New version of schemas created periodically, with arbitrary modifications to the structure.
* New elements are added to the schema vocabulary, and/or existing elements augmented or removed.

### Schema Versioning

Guardian Schemas are versioned using semantic versioning in the major.minor.micro format. Each number incremented sequentially to denote the following changes:

* major: the Schema version contains breaking changes.
* minor: the Schema version contains notable new capabilities and non-breaking changes.
* micro: the Schema release contains non-breaking changes only.

Guardian system does not generate versions automatically, it is the responsibility of the Schema authors (Standard Registry) to keep track of its policies/versions and correctly reflect changes in the version number.

Wherever possible and relevant, Guardian Schema version header contains a reference to the original (paper) document version from the guiding which this schema represents.

### Version Compatibility

Guardian Schema authors should take care to ensure that schema content is preserved to be backward compatible with earlier versions. A new Schema element should be added to the schema definition if/when it is necessary to make a non-backward compatible change. Schema existing elements should be removed/changed in accordance with the Schema deprecation policy.

### Non-breaking changes

The non-breaking changes to the Schema which do not warrant the change in the major version number are changes in:

* Changes in value to the descriptive elements, such as title, description and comment.
* Required/optional state of the element.
* New enum value in the “oneOf” element.
* New elements added to the schema not affecting existing elements in any way.

### Breaking changes

* Removing or renaming an element, changing any of its non-descriptive properties e.g. type or readOnly status.
* Changing in the values of ID elements.

### Schema version deprecation

Deprecation notice is used to inform the API users that a specific Schema version or an element is now considered obsolete and thus no longer advised for the use in applications. The notice is issued at least 2 months before the end-of-life date.

The notice is issued via the deprecated meta-data annotation, and via the Release Notes where the end-of-life date is also specified. On the date of the version expiry, a VC revocation notice is issued into the corresponding Hedera Topic.

A Schema may be discontinued without prior warning if the existing behaviour if incorrect or to patch a security vulnerability.

### Schema definition language

For the purposes of backwards compatibility Guardian differentiates between existing schemas and the creation of new schemas, and implements separate rules accordingly.

At this time Guardian does not version policy language definition separately from the Guardian, for the purposes over distinguishing the language definitions it is recommended to use Guardian release version numbers.

### Existing schemas

Due to long-term nature of some sustainability projects Policy Engine (PE) maintains unlimited ‘read’ backward compatibility with 'old’ schema definition language elements. In other words, new PE versions will recognize and be able to process all existing valid policies with schemas defined starting from the beginning of Guardian existence.

This does not guarantee that all schema elements will be processed in the same way as they previously were, nor displayed in the UI or accessed via APIs in the same way. New versions of Guardian would always recognize blocks/elements correctly, maintain the original policy workflow and meaning of the schema elements.

A schema element may become unsupported (ignored for processing triggering a warning) without prior warning if the existing behavior if incorrect or to patch a security vulnerability.

### New schemas

Each new version of Guardian may introduce changes to the schema language definition without prior notice. All changes will be reflected in the documentation for the release.

Furthermore, the use of ‘obsolete’ elements may become prohibited in the new versions/schemas created by the release. To clarify, on such occasions any ‘old’ versions or schemas would continue be supported in-use (in already established and/or new projects). However, any new schemas, including when created by copying the ‘old’ valid schema, containing the obsolete elements would not be accepted for ‘publishing’ or including into a policy. The authors would be required to remove/replace the ‘obsolete’ elements with new ones to create a supported schema definition.


# Repeatable Field Links

A repeatable field — a field with **Allow multiple answers** enabled — lets a user add as many entries as they need. Repeatable field links tie those entries to the entries of other repeatable fields, so every entry carries its own, separate set of related fields — including fields that live in other schemas of the same document.

#### The problem it solves

When a policy document tracks several parallel subjects — locations, activities, or measurement periods — each subject needs its own set of related data. Without linked fields, a user would have to manage that relationship manually, and the form has no way to enforce that each subject's data stays grouped together.

Repeatable field links enforce the one-to-one pairing automatically. A user adds one entry to the source field, and every linked field gains a matching entry. The entries stay paired through the entire lifecycle of the form.

#### How it works

When a policy is being filled in:

* Adding an entry to the source field creates a matching entry in every linked field. Linked fields have no manual add or remove buttons — they always follow the source.
* Each entry is labelled with the display name chosen during schema configuration, so entries are easy to identify.
* Fields marked as **Copied values** arrive filled and read-only in the linked entry.
* Removing a source entry prompts for confirmation, then removes its matching entry from every linked field. The remaining entries keep their own values.

Because the entries are paired one-to-one, conditions are also evaluated per entry. The same field can be shown in one entry and hidden in another, depending on the values each entry holds.

**Adding entries**

Add the source entries — here, two project locations:

Each location is its own block with its own fields:

Each linked section then gets a matching entry, labelled by the display name, with copied fields filled and read-only:

**Different fields for each entry**

Each entry runs its conditions independently. The first location chose *Quantification Approach 3* — its monitoring card expands and shows the conditional fields:

The second location chose *Quantification Approach 1* — the same card hides those fields:

#### Key distinctions

* **Cross-schema links are supported.** A dependent field can live in a different schema of the same document, not just in the same schema as the source.
* **Chains are supported.** A dependent field can itself be a source for another field, forming a group of any depth.
* **One source, many dependents.** A single source field can drive several dependent fields at once.
* **Conditions work with nested fields.** In the When clause, fields inside a repeatable group are available as a trigger — and the condition is evaluated independently for each entry.

#### Related

* Task: [Set up repeatable field links](/guardian/standard-registry/schemas/repeatable-field-links/set-up-repeatable-field-links)


# Set up Repeatable Field Links

Configure a source repeatable field to drive one or more dependent repeatable fields, so that adding an entry in the source automatically creates a matching entry in every linked field. See [Repeatable Field Links](/guardian/standard-registry/schemas/repeatable-field-links) for an explanation of how linked entries behave at form-fill time.

#### Prerequisites

* The schema is open in the schema editor.
* The schema contains at least one repeatable field (**Allow multiple answers** enabled) to use as the source, and at least one more to use as the dependent.

#### Steps

**1. Open the Repeatable links tab**

Switch to the **Repeatable links** tab in the schema editor. The tab shows the existing links defined for this schema.

**2. Add a link**

Fill in the link form and click **Add link**:

* **Source array** — the repeatable field that drives the group (for example, *Project Location*).
* **Dependent array** — the repeatable field that should follow the source (for example, *Baseline Emissions*). It can live in a different schema of the same document.
* **Display name** (optional) — a field from the source entry that labels each entry in the form.

Repeat to add more links. One source can drive several dependents, and a dependent can itself become the source for the next field.

**3. Copy values between entries (optional)**

Before clicking **Add link**, use **Add value** to map a field from the source entry to a field in the dependent entry. The value is copied automatically and shown as read-only. Add as many pairs as needed — they appear under **Copied values** in the link form.

**4. Save the schema**

Click **Save all**. Links, display names, and copied value pairs are stored with the schema.

**5. Add conditions for linked entries (optional)**

Switch to the **Conditions** tab and add a condition.

* In **When**, choose the controlling field. Fields inside linked entries are available here — not just top-level schema fields. Set the value that triggers the rule.
* In **THEN** and **ELSE**, add the target fields. Each target can be a single field or a whole sub-schema block. Selecting a block adds one target instead of listing every field it contains; it is marked with a **Sub-schema** tag.

Click **Save all**.

#### Result

The schema stores the configured links and conditions. When the schema is used in a policy:

* Adding a source entry creates a matching entry in every linked field, labelled with the display name.
* Copied fields arrive filled and read-only.
* Each entry evaluates its conditions independently, so the same field can appear in one entry and be hidden in another.

#### Related

* Concept: [Repeatable Field Links](/guardian/standard-registry/schemas/repeatable-field-links)


# Data Entry Updatability

### Overview

Data Entry Updatability: allows users to update specific fields based on a schema allowing updates to not material information to calculation.

At its core, this feature provides:

1\) the ability to mark “Simple” fields as updatable

2\) the ability to display all document versions, from the original to the latest (current) version

3\) when multiple VC versions exist, the latest (most recent) version is displayed or returned by default


# Demo using UI

[Step by Step](#step-by-step)

[Demo Video](#demo-video)

## Step By Step

## 1. Purpose

Allow users to edit documents and view all their versions.

### 2. Mark a field as available for update

Go to Manage Schema. Select the desired schema or create a new schema. Select the field with the Simple type, and the “Updatable field” field will become available. Check this box. Save form.

<figure><img src="/files/5YiVBwRz8wGrGs9egBSU" alt=""><figcaption></figcaption></figure>

**Note:** If the field type is not one of a Simple type, the value in the “Updatable Field” will be removed and will become non-editable.

<figure><img src="/files/fGNXYc1KPOVl0Csbjsbh" alt=""><figcaption></figcaption></figure>

## 3. Creating and Viewing Document Changes

Changes to a document can be created by the user who created the original document and is its publisher. For a user to edit a document, the document must not have the Revoked or Rejected status.

To create a new version, view the document in the published policy by clicking the “View Document” button, which will open the viewing form. If the current user is the document owner, a “Switch to Edit Mode” button will appear in the upper right corner.

<figure><img src="/files/FuYsshmyyNNTJgwSIjE7" alt=""><figcaption></figcaption></figure>

“Switch to Edit Mode” will be available to the document owner provided that the selected version of the document is the latest (current) version. Clicking this button will open the document in Edit mode.

<figure><img src="/files/IwXJzDLrPpuc9XtfSjSh" alt=""><figcaption></figcaption></figure>

In Edit mode, document information is displayed, and a button is available to switch back to form view mode.

Fields marked as “Updatable field” will be editable. After changing these fields, click “Save Changes” (becomes available if any changes have been made to the form).

<figure><img src="/files/4UQ83ZNy5hDajp5FhfnY" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/WdeRYUPqFEwqTyRR5JfC" alt=""><figcaption></figcaption></figure>

Close button: allowing you to continue making changes.

Save button: creates a new revision of a document and automatically switches to view mode.

If a document has multiple versions, a drop-down list of all document versions will appear.

<figure><img src="/files/sAC5Ig1Txw0v9pKmxJCH" alt=""><figcaption></figcaption></figure>

If the form has been modified and the user clicks the “Switch to View mode” button, a dialog box will appear. In this dialog box, the user can save their changes and switch to view mode or immediately switch to view mode without saving the changes.

When you select the desired version, information from the selected version is displayed.

<figure><img src="/files/sKE0lJFO4VUdLeAM6194" alt=""><figcaption></figcaption></figure>

**Note**: A user who is not the owner of a document cannot edit it but can view all versions of the document.

<figure><img src="/files/9sRkdoHeYz6QUoV7xcnm" alt=""><figcaption></figcaption></figure>

By clicking the “Approve” button from the grid, the user creates their own document based on the original (first) version of the document.

<figure><img src="/files/DD9LfuwosmX9eFiXXhrG" alt=""><figcaption></figcaption></figure>

When viewing the document history in “Trust Chain”, we can also see all versions of documents, starting from the most recent version and ending with the first one.

<figure><img src="/files/NCZ3cZ5DFDtXF7KgAYYI" alt=""><figcaption></figcaption></figure>

## 4. Indexer

Documents with multiple versions have a drop-down list with all versions. By default, the latest version of the document is selected.

<figure><img src="/files/x7g9GnRlQm2YgAhtCCtH" alt=""><figcaption></figcaption></figure>

When you select any version, information about the selected version is displayed.

<figure><img src="/files/16hesn2hr0VSpKOAYrUa" alt=""><figcaption></figcaption></figure>

## Demo Video

[Youtube](https://youtu.be/YMeY_bEOl_U)


# Demo using VM0042

1. First, we will import the VM0042 policy:
2. We will now edit some of the schema fields (Organization Name, contact person, Address,Email) as updatability field and save it.

<figure><img src="/files/n6JDerH0awQOup0ODeTj" alt=""><figcaption></figcaption></figure>

3. Once the changes are saved, we will now publish the policy:

<figure><img src="/files/XxhaenNXBJPSjLOmUWmW" alt=""><figcaption></figcaption></figure>

4. Now, we login as Project Proponent to submit project:

<figure><img src="/files/czg3kUj1MKWxuAYXhRud" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/ZuUHcsDk190N8KEvsr5x" alt=""><figcaption></figcaption></figure>

5. Once the project is submitted, we can view document by clicking on "View Document":

<figure><img src="/files/0lefemY2GKSSiLiYSLIK" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/n1o1kWJo1BotMKntHh2u" alt=""><figcaption></figcaption></figure>

6. We would now be able to change the document view to Edit mode if we need to change values of the fields, which were marked as Updatable field:

<figure><img src="/files/708DcP3acGHOi4QDPBs1" alt=""><figcaption></figcaption></figure>

7. Now, we would be changing the field: Organization name from MYCARBON3 to MYCARBONORG and save it.

<figure><img src="/files/pYZUISc0zNCW8RUqhnbX" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/729P5yBAkRZfw3nb3PD6" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/HmtF2hD2eErpBLrMeaul" alt=""><figcaption></figcaption></figure>

8. Once saved, we should be able to see two versions of the documents:

<figure><img src="/files/DkgWmiUuY5wrLabvb7Qk" alt=""><figcaption></figcaption></figure>


# Cross-Schema Conditions

A cross-schema condition lets a field in one referenced sub-schema control a field in a **different** referenced sub-schema on the same parent. The condition is defined on the parent schema that owns both sub-schema references.

### The problem it solves

Sub-schemas are designed to stay independent and reusable across policies. Sometimes a field in one sub-schema must determine a field in another sub-schema.

Without cross-schema conditions, the usual workaround is to merge schemas or duplicate fields on the parent. Both approaches reduce reuse and make maintenance harder.

Cross-schema conditions keep that relationship on the parent schema. Each sub-schema stays self-contained.

### How it works

A cross-schema condition uses the same `if/then/else` structure as a regular condition, with two key differences.

**The IF trigger is a nested field.** The `if` clause points to a leaf field inside one referenced sub-schema. The condition editor shows these fields grouped under each sub-schema name.

**THEN and ELSE target existing sub-schema fields.** The `then` and `else` branches point to fields that already exist inside referenced sub-schemas through **Sub-schema THEN** and **Sub-schema ELSE** targets.

When a branch is active, the target field appears in its sub-schema. When inactive, the field is hidden and must not appear in the submitted document.

Guardian compiles this into a standard JSON Schema `if/then/else` block on the parent schema. It uses nested `required` rules and `false` property constraints.

### Key distinctions

The condition belongs to the **lowest common ancestor**. This is the schema that references both the sub-schema containing the `if` field and the sub-schema containing the target field.

That placement keeps the sub-schemas independent. Neither sub-schema needs to know about the other.

### Related

* Task: [Configure Nested and Cross-Schema Conditions](/guardian/standard-registry/schemas/cross-schema-conditions/configure-nested-and-cross-schema-conditions)
* Reference: [Conditional and Visibility Logic](/guardian/standard-registry/schemas/best-practices-to-implement-schema/conditional-and-visibility-logic)
* Concept: [Cross-Schema Conditions](/guardian/standard-registry/schemas/cross-schema-conditions)


# Configure Nested and Cross-Schema Conditions

Set up a condition where the trigger field, the controlled fields, or both live inside referenced sub-schemas.

### Prerequisites

* The schema you are editing already has at least one field of type **Sub-Schema** referencing a loaded sub-schema.
* For cross-schema conditions, you need at least two Sub-Schema fields referencing different sub-schemas.

### Steps

#### Use a nested field as the IF trigger <a href="#use-a-nested-field-as-the-if-trigger" id="use-a-nested-field-as-the-if-trigger"></a>

1. Open the schema editor and scroll down to the **Conditions** section.
2. Click **Add Condition**.
3. Open the IF field picker. Fields are grouped: **This Schema** at the top, then one group per referenced sub-schema labelled with the sub-schema's name.
4. Select a field from one of the sub-schema groups.
5. Enter the match value in the field to the right of the picker.
6. Add THEN and ELSE fields using **Add THEN Field** and **Add ELSE Field** as normal.
7. Save the schema.

#### Add cross-schema targets to a THEN or ELSE branch <a href="#add-cross-schema-targets-to-a-then-or-else-branch" id="add-cross-schema-targets-to-a-then-or-else-branch"></a>

Continue from step 5 above, or open an existing condition that already has a nested IF field set.

6. Below the THEN fields area, open the **Add sub-schema THEN field or Add sub-schema ELSE field** dropdown and select a field from a sub-schema. That field appears when the condition is true. It appears as a **Sub-schema THEN** chip on the condition row.
7. Repeat for any additional target fields across other sub-schemas.
8. Save the schema.

{% hint style="info" %}
Sub-schema THEN alone already hides the target field in the form when the condition does not match.
{% endhint %}

### Result

When a user fills in the parent form:

* The condition from the IF field is taken from the target sub-schema.
* When its value matches: **Sub-schema THEN** or **Sub-schema ELSE** target fields appears in form.
* When its value does not match: **Sub-schema THEN** or **Sub-schema ELSE** target fields are hidden and must not be submitted.

### Troubleshooting

**Sub-schema fields do not appear in the IF picker.**\
The sub-schema must be fully loaded in the editor. If a group is missing, check that the Sub-Schema field has a valid schema type assigned and that the referenced schema is available in your policy context.

### Related

* Concept: [Cross-Schema Conditions](/guardian/standard-registry/schemas/cross-schema-conditions)
* Task: [Creating Schema using UI](/guardian/standard-registry/schemas/creating-system-schema-using-ui)
* Reference: [Conditional and Visibility Logic](/guardian/standard-registry/schemas/best-practices-to-implement-schema/conditional-and-visibility-logic)


# Adding Example Data

1. **Example:** To add example values to a schema, we need to click on "Example" option as shown below:

<figure><img src="/files/JieKFR3TU0HbbivTZ5EB" alt=""><figcaption></figcaption></figure>

Once you click on the above button, you will be able to fill all schema fields with sample values:

<figure><img src="/files/qruNT0VeWRAnS4NUjY7D" alt=""><figcaption></figcaption></figure>

2. **Preview** – shows a preview of how users will see the policy form during the execution of the policy

<figure><img src="/files/IHN1Scy5CSxP41AnVylr" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/NQ8zvrgsUBQW6TSeaQVF" alt=""><figcaption></figcaption></figure>

In Dry Run mode it is possible to quickly fill in the fields using the provided example values from the schema. This feature is most useful for testing/demonstrations or for experimenting and learning Guardian capabilities.

<figure><img src="/files/Ko0OORnre2NPVRrXMCay" alt=""><figcaption></figcaption></figure>


# Schema Differentiation

Schema differentiation refers to the process of distinguishing and categorizing schemas based on their characteristics, attributes, or purposes. It involves identifying and defining unique aspects of schemas to classify and manage them effectively within the system.


# Schema Differentiation using UI

We can compare two schemas by following some steps as follows:

## 1. Start Comparison by choosing Schemas:

**Step 1:**

We click on **Compare** button (last one) <img src="/files/aZ3hF8dFm8lnOPi5MgzH" alt="" data-size="line">present in Schemas tab as shown below:

<figure><img src="/files/C3opwVlQLViI2wEtPPdv" alt=""><figcaption></figcaption></figure>

**Step 2:**

Select two schemas for compare

<figure><img src="/files/0OGW4FxNF6X4wWodbb60" alt=""><figcaption></figcaption></figure>

## 2. Comparison View

### 2.1 Parameters

**UUID** : configures whether differences in UUIDs and Header IDs are taken into consideration when comparing blocks

| Parameter     | Definition                                                                                                                                                                                                                                                                                                                         |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Don't compare | UUIDs and Header IDs are not involved in comparison of the blocks and their Properties.                                                                                                                                                                                                                                            |
| All UUID      | <p>Differences in UUIDs and Header IDs are taken into consideration when comparing blocks and their Properties.<br><em>(For example, when two schemas are exactly the same in every property they will still be considered as different due to differences in the values of IDs which by definition are always different)</em></p> |

## 2.2 Sections

1\. **Main** – comparison of the main fields of schemas.

2\. **Schema Fields** – comparison results of the schema fields.

<figure><img src="/files/EqL8iNMCl2NKXPPanp5R" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/nnSSVMhWlyK5b79eIyzC" alt=""><figcaption></figcaption></figure>

**Display settings** *–* description and show/hide settings for each color/type of difference

| Color         | Purpose                                                                                                                                      |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Green         | fields are identical                                                                                                                         |
| Green - Amber | when fields are embedded schemas, and these schemas are identical. The fields themselves are not different because their UUIDs are different |
| Amber         | fields are partially equal                                                                                                                   |
| Red           | fields are absent in the other Policy                                                                                                        |

Field comparison displays can be unfolded to display a detailed view of the block Properties.


# Schema Tree

The Guardian platform is designed to facilitate the creation, management, and tracking of digital environmental assets with a focus on emissions reporting, carbon offset, and renewable energy credit creation. At the heart of the Guardian's functionality is the "Schema Tree," a structured framework that organizes and standardizes the data models used within the platform.

### What is a Schema Tree?

A Schema Tree in the Guardian is a hierarchical representation of data schemas that define the structure, rules, and relationships of the data entities involved in the environmental asset management process. It serves as a blueprint for constructing digital assets in a way that ensures consistency, reliability, and interoperability within the Guardian ecosystem and beyond.

### Purpose and Benefits

* **Standardization:** The Schema Tree provides a standardized approach to data modeling, which is crucial for the accurate and consistent representation of environmental assets across various applications and stakeholders.
* **Flexibility:** While offering a structured framework, the Schema Tree allows the customization of schemas to meet specific needs and requirements of different environmental projects and methodologies.
* **Interoperability:** By adhering to a common set of schemas, digital environmental assets created within the Guardian platform can easily be shared, exchanged, and verified across different systems and networks, enhancing collaboration and transparency in the environmental sector.

### How it Works

The Schema Tree is composed of nodes representing different data entities, such as project details, emissions data, verification reports, and more. Each node in the tree is defined by a schema that specifies the attributes, data types, and validation rules for that entity. These schemas are interconnected, reflecting the relationships and dependencies among the various entities involved in environmental asset management.

For instance, a project node may be linked to multiple emissions report nodes, which in turn may be linked to verification report nodes. This hierarchical structure not only organizes the data logically but also facilitates the aggregation, analysis, and reporting of environmental impact data.


# Schema Tree UI

## 1. Viewing Schema Tree

Schema tree hierarchy can be viewed by clicking on Tree button for each Policy Schema or Tool Schema as shown below:

<figure><img src="/files/jzAuT83ZiEnXkhbWpNXF" alt=""><figcaption></figcaption></figure>

We can move the image by holding and moving the mouse.

Each schema and its child schemas are represented by same color in parent to child fashion.

<figure><img src="/files/puu5BcaAzsJwgT3CkTxS" alt=""><figcaption></figcaption></figure>

## 2. Downloading Tree

Schema Tree hierarchy can be downloaded by clicking on Download icon:

<figure><img src="/files/9DJoDA2qjedoWbCGboCR" alt=""><figcaption></figcaption></figure>

## 3. Demo Video

[Youtube](https://youtu.be/8FxSSO0ttoQ?si=HjrV-8r_zkHWQAWD\&t=100)


# API for Returning Schema Tree

## Returns schema tree.

<mark style="color:blue;">`GET`</mark> `/schema/{schemaId}/tree`

Returns schema tree.

#### Path Parameters

| Name                                       | Type   | Description       |
| ------------------------------------------ | ------ | ----------------- |
| schemaId<mark style="color:red;">\*</mark> | String | Schema identifier |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```
content:
            application/json:
              schema:
                type: object
                properties:
                  name:
                    type: string
                  type:
                    type: string
                  children:
                    type: array
                    items:
                      type: object
```

{% endtab %}

{% tab title="401: Unauthorized Unauthorized" %}

{% endtab %}

{% tab title="403: Forbidden Forbidden" %}

{% endtab %}

{% tab title="500: Internal Server Error Internal Server Error" %}

```
content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalServerErrorDTO'
```

{% endtab %}
{% endtabs %}


# Export Schema Tree as PlantUML

## 1. Opening Export Dialog

The Schema Tree can be exported as a PlantUML class diagram. To export, open the Schema Tree view by clicking the **Tree** button for the desired schema, then click the **Export PlantUML** button:

<figure><img src="/files/PJISwu48wUli5HRMTYq7" alt=""><figcaption></figcaption></figure>

## 2. Export Options

The Export PlantUML dialog provides three checkboxes to control the level of detail:

* **Include Fields** — Adds field names and descriptions to each schema class. Enabled by default.
* **Include Formulas** — Adds formula packages with stereotyped elements (constants, variables, formulas, text) and cross-formula links.
* **Include Dependencies** — Expands the diagram to include formulas and schemas referenced by directly linked formulas. Requires **Include Formulas** to be enabled.

<figure><img src="/files/OpMKgNWRPwPUD8hyjRRW" alt=""><figcaption></figcaption></figure>

## 3. Exported File

Clicking **Download** generates and downloads a `.puml` file that can be rendered in any PlantUML-compatible tool (e.g., PlantUML online editor, IntelliJ IDEA, VS Code extensions).

The diagram includes:

* **Schema classes** with parent-child composition arrows
* **Fields** with names and descriptions (when enabled)
* **Formula packages** grouping constants, variables, formulas, and text elements (when enabled)
* **Cross-formula links** shown as dependency arrows (when enabled)
* **Color coding** per element type for easy visual identification


# Export Schema Tree in PlantUML Format API

## Returns schema tree in PlantUML format.

<mark style="color:blue;">`GET`</mark> `/schema/{schemaId}/tree/export/plantuml`

Returns the schema tree as exportable PlantUML code. The response is a plain-text `.puml` file. Users with the `SCHEMAS_SCHEMA_READ` permission are allowed to make the request.

#### Path Parameters

| Name                                       | Type   | Description       |
| ------------------------------------------ | ------ | ----------------- |
| schemaId<mark style="color:red;">\*</mark> | String | Schema identifier |

#### Query Parameters

| Name                | Type    | Description                                                                                                     |
| ------------------- | ------- | --------------------------------------------------------------------------------------------------------------- |
| includeFields       | Boolean | Include field names and descriptions in classes. Defaults to `true`.                                            |
| includeFormulas     | Boolean | Include formula components and links. Defaults to `false`.                                                      |
| includeDependencies | Boolean | Include dependent formulas referenced by linked formulas. Defaults to `false`. Requires `includeFormulas=true`. |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```
content:
            text/plain:
              schema:
                type: string
              headers:
                Content-Disposition:
                  schema:
                    type: string
                    example: attachment; filename="schema-tree-{schemaId}.puml"
```

{% endtab %}

{% tab title="401: Unauthorized Unauthorized" %}

{% endtab %}

{% tab title="403: Forbidden Forbidden" %}

{% endtab %}

{% tab title="500: Internal Server Error Internal Server Error" %}

```
content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalServerErrorDTO'
```

{% endtab %}
{% endtabs %}


# Schema Tags

Schema Tags are descriptive labels or metadata for schemas. Tags provide a way to categorize, organize, and search for schemas based on their characteristics, attributes, or purposes. Tagging schemas in Guardian helps users easily identify and manage schemas based on their specific needs or criteria.


# Adding a Schema Tag

## Schema Tags

Tags can have attached/linked documents. To add a document to the tag a schema is required. Such documents can be found under the **Tag** section.

<figure><img src="/files/VVWnH52zh1UbA06ezvFR" alt=""><figcaption></figcaption></figure>

Users can select one of the published schemas in the section when adding a tag to add a corresponding document to the tag being created.


# Schema Rules

1. [Step By Step Process](#id-1.-step-by-step-process)
2. [Demo Video](#id-2.-demo-video)

## 1. Step By Step Process

## **Schema rules**

Schema rules have been created to enable authorised policy users to offer assistance to other users (and/or themselves) with data input and/or data evaluation. Schema rules define acceptable values and their ranges for schema fields (and correspondingly input fields in Guardian forms). They are activated in the UI whenever the form is viewed by users, and re-evaluated every time any of the values on the form is changed. Rules can contain mathematical formulas and logical if-then-else flow, and source data from any field in the current schema as well as any other schemas/documents that are present in the corresponding policy. When rules are evaluated they produce a binary ‘pass/fail’ output, which is displayed in the UI as green and amber field highlights correspondingly.

### **1. Creation**

#### **1.1 List of schema rules**

Each Policy can have associated by Schema rules. The list of schema rules is displayed in the corresponding section of the UI, which provides the facility to enable/disable each of them individually.

![](/files/F2tPUvzLcPqUgYw0jssb)

#### **1.2 Creation**

To initiate the creation of a new schema rules users need to click on the ‘Create New’ button in the corresponding UI section.

<figure><img src="/files/b5KxUAaRYA0OsTYmIOPF" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Qqq3Ox8YK0VHMWHbDFOW" alt=""><figcaption></figcaption></figure>

#### **1.3 Configuration**

After a rule has been created it should be configured to be meaningful, the process can be started by clicking the edit icon in the rules grid.

![](/files/pyLZq6dyLbO2rMYt63O5)

**1.3.1 General configuration**

Specifying the rules name and its ‘target’ policy is mandatory.

![](/files/oGueRSnrSiw90XnPm0wU)

**1.3.2 Configuring fields and schema**

To source data from documents rule creators need to specify which fields from which schemas should be retrieved. Schema tree view shows policy schemas in a hierarchical structure, and allows to select the target fields.

![](/files/KMYOyK5tpgWk9rqj9kso)

**1.3.2.1 Search**

In complex policies the complexity of schema structures can be difficult to navigate, rules creators could use search tool to optimize their work.\\

<figure><img src="/files/irmIZSgkWxxcem6OX4BL" alt=""><figcaption></figcaption></figure>

**1.3.2.2 Selection**

Clicking on a schema box opens the side menu which lists all the fields available in the selected schema.

![](/files/vaanCblHzn1Cg9nLYoqo)

\
\&#xNAN;*Note: sub-schemas do not produce corresponding document, when such sub-schema is selected in the schema view the right hand panel shows the fields from the parent schema of which this sub-schema is a part.*

**1.3.2.3 Properties**

By default searching for fields is performed on the basis of the values in their description field, however it is possible to search for matches in their ‘property’ values by navigating into the corresponding tab.\\

<figure><img src="/files/yxrHiOfjqzdBDrp608Y6" alt=""><figcaption></figcaption></figure>

*Note: some schema fields might not have or have empty property fields, such cases are displayed as greyed-out items in the list and their ‘description’ field is shown instead*

**1.3.3 Configuring formulas**

The selected schemas and their fields constitute ‘input’ data for the rules. The second stage of rule configuration is specifying the rules themselves and their formulas.

The system automatically creates short variable names for the target fields, each of which then can be used as a rule target (for which to specify the acceptable values/ranged) or used in a formula to specify those for another field variable.

![](/files/UtVBTDdtTkcFPTKAUTs0)

**1.3.3.1 Editing rules**

<figure><img src="/files/DijGWXm2AVUrNnOA3Z0P" alt=""><figcaption></figcaption></figure>

There are a number of templates that can be used when configuring or editing rules. When a template is not selected for an existing rule it indicates that the rule is effectively non-existent for this field.\\

<figure><img src="/files/ZrS3JScPB91sWEoDrOiu" alt=""><figcaption></figcaption></figure>

**1.3.3.1 Templates**

* **Formula**

Formula is the most flexible and most powerful rule template.

Formulas must be configured such that their evaluation results in a true or false values (or numerical 0/1). Formulas support mathematical operations from <https://mathjs.org/> and Microsoft Excel function as supported by <https://formulajs.info/functions/>. Formulas can feature any or all fields which have been selected in the previous steps.

<figure><img src="/files/6sAkpuYSAIx6KFTFkwPj" alt=""><figcaption></figcaption></figure>

* **Range**

Ranges are simplified rules which verify that the value of the target field falls between the two borderline values specified.

![](/files/D7Y34gl6q3X08f3Wk8D7)

* **Condition**

This template allows for configuration of logical flows which can evaluate conditions and employ different formulas depending on the results of those evaluations.

**IF** – a condition to evaluate , must evaluate to ‘true’ or ‘false’\
**THEN** – the rule if the condition is ‘true’\
**ELSE** – the rule which would would be employed if none of the ‘if’ conditions above resolved to ‘true’

*Note: in cases where more than one ‘if’ condition would resolve to true only the first ‘then’ gets applied*

<figure><img src="/files/qUTUr5Z7GVWhdCjAjamj" alt=""><figcaption></figcaption></figure>

The conditions are specified as formulas, which are subject for the principles and conventions specified above.

Formulas support notations for the following typical operations:

* **Text –** compare the values of a textual field to a text
* **Range –** simplified notation to check if the value is in the specified range
* **Enum –** if the field of a type ‘enum’ this option allows the selection of a single or multiple values from the enum for matching. If any of these values match the formula is considered to have been resolved to ‘true’.

<figure><img src="/files/W1AAGx3TYFR7UQWI16m6" alt=""><figcaption></figcaption></figure>

**1.3.3.3 Preview**

Preview option helps users to test the behaviour of the formulas during their configuration.

![](/files/g5GjwX6eHtQY8UxBVblw)

\
Users are required to manually populate the values for the ‘input’ fields so to trigger the evaluation of the formulas.

![](/files/KxyPbWzbv5ytrwO5EZzo)

If the formula contains an error, or the system is unable to calculate the resulting value the result field would be highlighted in red.

![](/files/sa3yCGfEkAliOF34u2H1)

If the evaluation was successful the result field would be highlighted in amber (if the value ‘failed’ the evaluation) or in green (if it was a ‘success’).

![](/files/Mxtmrq9Op0WS3MHkvOLK)

![](/files/Mxtmrq9Op0WS3MHkvOLK)

Once all editing is done the template must be saved.

### **2. Publishing**

Rules can not be published externally. The equivalent action which makes the system to apply rules as describe above is their ‘activation’.

**Note: Rules can be activated/deactivated at any time.**

### **3. Evaluation.**

Rules would be downloaded and evaluated every time a document with the associated active rules is being edited via the corresponding Guardian form.

Rules are also valued when such document is being viewed.

New rules would be applied to the documents which have been created before the rules have been specified or activated.

### **4. Access control**

There are specific permissions for working with rules

* **Read**, **Create** – allows to view, create new, and activate existing schema rules
* **Execute** – allows to evaluate the existing rules when editing or viewing their corresponding documents

By default Standard Registries are assigned all 3 permissions. Default role has only Evaluate permission.

### **5. Import\Export**

Schema rules can be exported to and imported from files.

When importing the rules they effectively become the rules of the importing Guardian instance with no dependency or relations to the instances that originally produced and exported the rules.

## 2. Demo Video

[Youtube](https://youtu.be/RQYxEh_cmSU?si=MJUlII3Tl4KTXfd0\&t=91)


# Schema Predefined Values

1. [Step By Step Process](#id-1.-step-by-step-process)
2. [Demo Video](#id-2.-demo-video)

## 1. Step By Step Process

## 1. Schema Predefined Values

Predefined schema values allow users to set up values for each field in schema (number, string, GeoJSON, or other nested schema) and use them in policy while displaying request blocks. There are 3 types of predefined values:

* **Default Value** - This value will be used in the document in the absence of user input. I.e. Guardian pre-populates the field with the Default Value which, if not changed explicitly by the user, would appear in the resulting document as if it was input by the user.
* **Suggested Value** - This provides an example of the correct value a user could input into the field. Unlike ‘Default Value’ it is not inserted automatically into the document, it just serves as a visual aid for users filling out the form.
* **Test Value** - This will be used for quick filling out the form for testing in Dry-Run mode. When the ‘Test’ button is clicked all fields in the form which have associated ‘Test Value’ will be auto-populated with these values correspondingly, so the user can quickly proceed to the next step in the policy flow with valid test data in the resulting document.

### 1.1 Setting Predefined Values:

Predefined values can be found in the schema configuration dialog.

There is “Selected values” block and “Show More”/”Show Less” button there.

![](/files/SMbwxwv6tJAEosS7lom8)

![](/files/RjYbDFEaW0hXED6IWRPq)

### 1.1.1 Default value

The default value is the initial field value, which will be marked with gold color until it won’t be changed

![](/files/q7nMdk8b6rPxV5MxxWJe)

### 1.1.2 Suggest value

The suggest value is the value, which will be suggested when field value is empty

![](/files/G0T1JLxIAzYSrgLsRpjc)

### 1.1.3 Test Value

The test value is the value, which will be inserted after clicking on the “Test” button. **It is only available in Dry-Run mode.**

![](/files/LoVDyG6jjy0Wg1RV2heG)

### 2. Complex cases

Predefined values can also be used in more complex cases such as multiple fields, nested schemas, geoJSON.

![](/files/aUehtODRmjxphpK5UZDx)

![](/files/FOYtxa2gmD6ld8pNWBAn)

![](/files/cV9cjvQm6v9oA0Jn5uhq)

## 2. Demo Video

[Youtube](https://youtu.be/wFRk9uHRXss?si=2Gx2FNq6Tk9PnkIR\&t=104)


# How to handle large geospatial files?

## 1. Step By Step:

1. Users can upload **.kml** or **.json** files to populate *geoJson* fields with locations.

<figure><img src="/files/81GW2AThSeAuD9Cre1VX" alt=""><figcaption></figcaption></figure>

2. The imported locations appear as grey shapes overlaid on the map.

<figure><img src="/files/aB5dtqbQpWW3fUYz2rJ3" alt=""><figcaption></figcaption></figure>

To select a location, click its shape on the map. The shape will be highlighted in green, and its textual definition will appear in the editable panel below the map. You can add, modify, or delete multiple locations. Clicking a selected location again will deselect it.

3. You can also use the **“Include all”** option to import all locations from the uploaded file.

<figure><img src="/files/LVl6swKQI0tRQI93pQ0V" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
**Note:** Web browsers limit the size of items they can render. The exact threshold depends on the host computer’s hardware and operating system configuration. If an uploaded file exceeds these limits, Guardian UI displays a warning message.
{% endhint %}

4. When these limits are reached, Guardian UI also provides an option to download the files by clicking the corresponding button in a modal window.

<figure><img src="/files/5xb6Kdkn3pnuTCI60cPU" alt=""><figcaption></figcaption></figure>

## 2. Demo Video:

[Youtube](https://youtu.be/Iuvdi3CP6O4?si=3s7mwrWsD8_M0I8d\&t=113)


# Policies

A policy is a set of rules, roles, workflows, and data-handling logic that governs how credentials (VCs), attestations, and reports are issued, verified, and used within a sustainability methodology or project.\
It acts like a smart contract template for dMRV, but instead of code on-chain, it’s orchestrated off-chain through the Guardian framework, with critical checkpoints anchored to Hedera.

#### **Key Components of a Policy**

1. **Roles & Permissions**
   * Defines which actors (e.g., Project Developer, Verifier, Standard Body, Registry) can perform specific actions.
   * Example: Only a Verifier role can issue verification credentials.
2. **Schemas**
   * Policies use schemas to structure the data being collected or issued as credentials.
   * Example: A "Project Description VC" schema or "Monitoring Report VC" schema.
3. **Workflows**
   * Step-by-step processes for participants.
   * Example: A Project Developer submits project details → Verifier reviews → Standard Body approves.
4. **Rules & Conditions**
   * Validation checks on data, sequencing of steps, and compliance enforcement.
   * Example: A monitoring report VC must match the schema and include forest carbon flux data before approval.
5. **Credential Lifecycle**
   * Policies define when and how Verifiable Credentials (VCs) and Verifiable Presentations (VPs) are created, validated, mapped, or revoked.
6. **Automation & Anchoring**
   * Automates issuance, verification, and tracking of digital assets (tokens, credits).
   * Anchors hashes of VCs/VPs to the Hedera Consensus Service (HCS) or Hedera Token Service (HTS) for transparency and immutability.


# Policy Glossary

Next, we discuss the terms that need to be understood to create Policies within the Guardian framework:

| Term                  | Definition                                                                                                          | Example                                                                                                                         |
| --------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Block                 | Either a Policy Workflow or a Policy Action                                                                         | MRVDataVerification (Policy Workflow)                                                                                           |
| `children`            | Defines a list of Blocks that are grouped into a Policy Workflow                                                    | List of Blocks                                                                                                                  |
| `defaultActive`       | Determines if Policy Workflow or a Policy Action can be executed                                                    | `true`                                                                                                                          |
| `permissions`         | Security Policy associated with a specific role                                                                     | `STANDARD_REGISTRY`                                                                                                             |
| `blockType`           | Specifies the type of Policy Workflow or Policy Action                                                              | `interfaceContainerBlock` (policy workflow name)                                                                                |
| `uiMetaData`          | Specifies the data of the policy workflow and/or Policy Action to be displayed                                      | `type: header___` `fields:___________` `name: document.issuer` `title: Owner_____` `type: text`                                 |
| `tag`                 | Specifies the ID of a policy action which can be referenced in other blocks as a dependency                         | `Request`                                                                                                                       |
| `schema`              | Defines the data schema for a block                                                                                 | `Installer` or `MRV`                                                                                                            |
| `dataType`            | Specifies the Type of data used in the Block                                                                        | `source`                                                                                                                        |
| `dependencies`        | Specifies which blocks `tag` or state transition rules `stateMutation`                                              | See `tag` for referencing other Policy actions and `stateMutation` is a specific example of the name of a state transition rule |
| `roles`               | Available roles from which the user can choose.                                                                     | `Auditor`                                                                                                                       |
| `cyclic`              | Go back one step to enable the creation of the previous object.                                                     | `true`                                                                                                                          |
| `stop propagation`    | End processing here, don't pass control to the next block.                                                          | `true`                                                                                                                          |
| `entityType`          | Gives the document a label in the DB. Needed for filtering.                                                         | `Installer`                                                                                                                     |
| `forceNewDocument`    | Adds new Document                                                                                                   | `true`                                                                                                                          |
| `options`             | List of attributes, which is added to the VC when it is being persistent. Can be used for more flexible filtration. | <p>"name": "status"</p><p>"value": "Minted",</p>                                                                                |
| `documentType`        | Type of Document                                                                                                    | VC/VP/DID                                                                                                                       |
| `topic`               | Specifies Topic Name                                                                                                | topic                                                                                                                           |
| `actor`               | Specifies a person, who will be next Owner                                                                          | Owner/Policy Owner                                                                                                              |
| `issuer`              | Specifies a person, who will be Signer                                                                              | owner / Policy Owner                                                                                                            |
| `onlyOwnDocuments`    | Specifies whether a block applies to only those documents owned by the role specified in `permissions`              | `true` or `false`                                                                                                               |
| `ViewHistory`         | Specifies documents in the Grid with status timeline                                                                | `true` or `false`                                                                                                               |
| `on errors`           | Specifies if the error has occurred in the Block                                                                    | Retry/Go to step/Go to tag                                                                                                      |
| `onlyAssignDocuments` | Specifies which VC should be assigned to the user                                                                   | `true` or `false`                                                                                                               |


# Policy Creation

Policy creation in Hedera Guardian is the foundation for digitizing sustainability standards. It transforms rules into automated, transparent workflows, ensuring trust, compliance, and scalability in environmental asset management.

**Importance of Policy Creation**

1. **Standardization of Methodologies**
   * Digitizes environmental standards into consistent, enforceable rules.
   * Ensures all participants follow the same verified process.
2. **Transparency & Trust**
   * Anchors policy actions (VCs, approvals, tokens) to Hedera.
   * Creates an immutable, auditable trail of activities.
3. **Automation of Workflows**
   * Replaces manual verification with automated checks and triggers.
   * Reduces errors, costs, and administrative overhead.
4. **Interoperability**
   * Policies use W3C-compliant VCs and schemas, enabling global compatibility across registries, standards bodies, and marketplaces.
5. **Flexibility & Governance**
   * Supports versioning for methodology updates.
   * Allows controlled deprecation of outdated policies.
6. **Scalability**
   * Enables large-scale deployment of sustainability projects (thousands of projects under a single policy template).
7. **Regulatory Compliance**
   * Encodes the requirements of standards bodies into enforceable workflows.
   * Provides verifiable proof of compliance for audits and reporting.


# Available Policy Workflow Blocks

Starting with the [Wikipedia definition](https://en.wikipedia.org/wiki/Workflow_engine), a Policy Workflow Engine (PWE) is a software application that manages business processes based on business rules and business data which are defined within the context of a specific policy. A PWE, therefore, manages and monitors the state of required policy actions and the required information flow in a policy grouped into a policy workflow, and determines which are the next policy actions based on the state of a policy workflow. The policy actions may be anything from saving an application form in a document management system to sending a reminder e-mail to users or escalating overdue items to management. Policy Workflow Blocks enable different business logic to exist within the Guardian’s PWE.

### Available Policy Workflows Blocks

<table><thead><tr><th align="center">Block</th><th width="226.33333333333331" align="center">Definition</th><th align="center">Documentation Link</th></tr></thead><tbody><tr><td align="center">InterfaceContainerBlock</td><td align="center">A block which contains and organizes other blocks.</td><td align="center"><a href="/pages/KxODrErWroJ2Qfr6hTZw">InterfaceContainerBlock</a></td></tr><tr><td align="center">PolicyRolesBlock</td><td align="center">A block which determines a role for the user.</td><td align="center"><a href="/pages/6cVQzZ2iITgvyjt7Ixvc">PolicyRolesBlock</a></td></tr><tr><td align="center">InterfaceStepBlock</td><td align="center">Similar to the InterfaceContainerBlock, with the difference that it can only render a single child element.</td><td align="center"><a href="/pages/WVfvk2CXNaNTrkewRkzw">InterfaceStepBlock</a></td></tr><tr><td align="center">requestVCDocumentBlock</td><td align="center">A type of the block which creates a form from the schema, and sends the document to the server.</td><td align="center"><a href="/pages/OdPt6rpdp9tg9zmpUGQy">requestVCDocumentBlock</a></td></tr><tr><td align="center">sendToGuardianBlock</td><td align="center">A type of the block which can save a new or updated document.</td><td align="center"><a href="/pages/puXpj9PkEjjZGUsnCCHN">sendToGuardianBlock</a></td></tr><tr><td align="center">reassigningBlock</td><td align="center">A type of block which re-signs the document and change the user to document owner.</td><td align="center"><a href="/pages/SuNKxcpCnK4w7BcaDXfl">reassigningBlock</a></td></tr><tr><td align="center">InformationBlock</td><td align="center">A block type which can display a notification or a progress bar.</td><td align="center"><a href="/pages/IYvxjIVuBQENGCUCEDg9">InformationBlock</a></td></tr><tr><td align="center">InterfaceDocumentsSourceBlock</td><td align="center">A block type which outputs information from the DB as grid.</td><td align="center"><a href="/pages/qGivLPcEvQDctVr3EHYA">InterfaceDocumentsSourceBlock</a></td></tr><tr><td align="center">paginationAddon</td><td align="center">A block type which adds pagination to the InterfaceDocumentSourceBlock if added</td><td align="center"><a href="/pages/5DMoBqPR2qCFUYgkftc9">paginationAddon</a></td></tr><tr><td align="center">DocumentsSourceAddOn</td><td align="center">A type of block for searching VC as grid</td><td align="center"><a href="/pages/hCyLKjNs5h8wqo8DGhqs">DocumentsSourceAddOn</a></td></tr><tr><td align="center">filtersAddOn</td><td align="center">A child block for 'DocumentsSourceAddon'. Contains additional dynamic filters</td><td align="center"><a href="/pages/KJ45lTZnsbcxYLvKBCHX">filtersAddOn</a></td></tr><tr><td align="center">InterfaceActionBlock</td><td align="center">A block to create custom actions.</td><td align="center"><a href="/pages/mfI9prQxOERUc2JvH5G7">InterfaceActionBlock</a></td></tr><tr><td align="center">externalDataBlock</td><td align="center">Receives data from the external source and passes them over the the next block.</td><td align="center"><a href="/pages/VnMehxszXX5tjEYiaVSY">externalDataBlock</a></td></tr><tr><td align="center">retirementDocumentBlock</td><td align="center">Receives the VC from the previous block and retires based on the rule(s).</td><td align="center"><a href="/pages/xjVnuec3JH8dXBnIDIgA">retirementDocumentBlock</a></td></tr><tr><td align="center">calculateContainerBlock &#x26; calculateMathAddonBlock</td><td align="center">The blocks to calculate. calculateContainerBlock: Receives VC from the previous block. Passes the new VC to the next block.<br>calculateMathOnBlock: Child block for 'calculateContainerBlock'. Contains descriptions of variables and formulas.</td><td align="center"><a href="/pages/i1trk19OS6iAUedFuZa1">calculateContainerBlock &#x26; calculateMathAddonBlock</a></td></tr><tr><td align="center">reportBlock</td><td align="center">The block container for TrustChain.</td><td align="center"><a href="/pages/QYnMFSQa8Qn8BFMxhuNp">reportBlock &#x26; reportItemBlock</a></td></tr><tr><td align="center">reportItemBlock</td><td align="center">The block for setting up the elements of the TrustChain.</td><td align="center"><a href="/pages/QYnMFSQa8Qn8BFMxhuNp">reportBlock &#x26; reportItemBlock</a></td></tr><tr><td align="center">Switch Block</td><td align="center">This block transfers execution to one or more blocks depending on the parameters</td><td align="center"><a href="/pages/dLgS4AgoVq8GL1NEym47">switchBlock</a></td></tr><tr><td align="center">timerBlock</td><td align="center">timer object which triggers the event</td><td align="center"><a href="/pages/SagNI0ixuyRHv6HKDaht">TimerBlock</a></td></tr><tr><td align="center">aggregateDocumentBlock</td><td align="center">block responsible for aggregation of the documents</td><td align="center"><a href="/pages/zFQThAsM0upts6ARbWYG">aggregateDocumentBlock</a></td></tr><tr><td align="center">revocationBlock</td><td align="center">This Block finds related messages in policy topics, and revokes those messages and sends it to Hedera topic, but it doesn’t save documents in DB</td><td align="center"><a href="https://github.com/hashgraph/guardian/blob/develop/docs/available-policy-workflow-blocks/broken-reference/README.md">revocationBlock</a></td></tr><tr><td align="center">setRelationshipsBlock</td><td align="center">Contains DocumentSourceAddOn Block and set relationships for input document.</td><td align="center"><a href="/pages/sMDDscLghqoLYA5CXYrC">setRelationshipBlock</a></td></tr><tr><td align="center">buttonBlock</td><td align="center">Block responsible for creating buttons</td><td align="center"><a href="/pages/jMBjK6bUPfQ0Iwiqk85j">buttonBlock</a></td></tr><tr><td align="center">documentValidatorBlock</td><td align="center">Block to validate documents, including linked documents</td><td align="center"><a href="/pages/3UBIc4ZGijP4jiQuyYHl">documentValidatorBlock</a></td></tr><tr><td align="center">tokenActionBlock</td><td align="center">Block is responsible to automation actions related to tokens</td><td align="center"><a href="/pages/GjcQtvUZHIzn74EAQPt3">tokenActionBlock</a></td></tr><tr><td align="center">tokenConfirmationBlock</td><td align="center">Block enables the owner of the private key for the account to manually perform operations with the token</td><td align="center"><a href="/pages/2aLCDJb0tM88NjC4lVYp">tokenConfirmationBlock</a></td></tr><tr><td align="center">mintDocumentBlock</td><td align="center">Block is responsible for adding configurations on calculating the amount of tokens to be minted.</td><td align="center"><a href="/pages/LvR7TaF526HGBWSxyEZm">mintDocumentBlock</a></td></tr><tr><td align="center">groupManagerBlock</td><td align="center">Block allows to manage group membership, add and remove users from the group.</td><td align="center"><a href="/pages/U5STCXaxOKLpaqDrSt5C">groupManagerBlock</a></td></tr><tr><td align="center">multiSignBlock</td><td align="center">This block provides a way to specify multiple signators for a single VC document, and then create a VP based on it.</td><td align="center"><a href="/pages/NHxvGSgIWjJv60eOw1oQ">multiSignBlock</a></td></tr><tr><td align="center">customLogicBlock</td><td align="center">This block is used to perform Logic</td><td align="center"><a href="/pages/mCbPfxcWwvqbprP1lJOe">customLogicBlock</a></td></tr><tr><td align="center">splitBlock</td><td align="center">This block allows to accumulate VC documents and produce new VCs in fixed chunks</td><td align="center"><a href="/pages/2yH80UWsIHapByG9wwfk">splitBlock</a><br></td></tr><tr><td align="center">wipeDocumentBlock</td><td align="center">This block is used to wipe the Token</td><td align="center"><a href="https://github.com/hashgraph/guardian/blob/develop/docs/guardian/standard-registry/policies/policy-creation/introduction/broken-reference/README.md">wipeDocumentBlock</a></td></tr><tr><td align="center">CreateTokenBlock</td><td align="center">This block is used to create Token template</td><td align="center"><a href="/pages/LSvvaP9Jrb8avf59K765">CreateTokenBlock</a></td></tr><tr><td align="center">impactAddon</td><td align="center">This is an addon to create token impacts</td><td align="center"><a href="/pages/Gcy0v39C4ux2xZQ0xoLQ">impactAddon</a></td></tr><tr><td align="center">Http Request Block</td><td align="center">This block is used to retrieve outside data</td><td align="center"><a href="/pages/QOuvJYVfvjBwtEHWpH3S">HttpRequestBlock</a></td></tr><tr><td align="center">historyAddon</td><td align="center">This block turn on history on interfaceDocumentsSourceBlock.</td><td align="center"><a href="/pages/7kKkvzHlZvffCf7fvilg">historyAddon</a></td></tr><tr><td align="center">selectiveAttributes Block</td><td align="center">This block will filter attributes (option field) in documents returned by documentsSourceAddon.</td><td align="center"><a href="/pages/j3ITkl65tpokLFMpDlrN">selectiveAttributesBlock</a></td></tr><tr><td align="center">tagsManagerBlock</td><td align="center">This block is responsible for managing tags in policies.</td><td align="center"><a href="/pages/KZ9Lgru34543M7URuJ0g">tagsManagerBlock</a></td></tr><tr><td align="center">externalTopicBlock</td><td align="center">This block allows to configure the link to Hedera topics established by other policy instances for monitoring of ‘document published’ messages and ingestion of the targeted VC documents.</td><td align="center"><a href="/pages/sLicPNEMM5018563LA9G">externalTopicBlock</a></td></tr><tr><td align="center">messagesReportBlock</td><td align="center">This block allows to create report based on the inter-referenced messages.</td><td align="center"><a href="/pages/wUHIkdUTzdXf6l9YPcEc">messagesReportBlock</a></td></tr><tr><td align="center">notificationBlock</td><td align="center">This block is used to generate notifications</td><td align="center"><a href="/pages/a0GgrJuB7YVC4kvtv1SK">notificationBlock</a></td></tr><tr><td align="center">extractDataBlock</td><td align="center">This block extractDataBlock provides means to extract a data set which corresponds to any of these embedded schemas (at any depth level)</td><td align="center"><a href="/pages/rJqnI3cyR8cKRnqmzogS">extractDataBlock</a></td></tr><tr><td align="center">button block Addon</td><td align="center">This block is used to display interactive buttons</td><td align="center"><a href="/pages/6P1jyg1XPOZpppkpTmTJ">buttonBlockAddon</a></td></tr><tr><td align="center">Dropdown Block Addon</td><td align="center">The block is to display an interactive dropdown menu</td><td align="center"><a href="/pages/cRaUevRVZ6PmMsh7qvQQ">dropdownBlockAddon</a></td></tr><tr><td align="center">RequestVC Document Block Addon</td><td align="center">This block is to display an interactive button in the interfaceDocumentsSourceBlock.</td><td align="center"><a href="/pages/gbV9YRoUDNKvbhJoWQ5E">requestVcDocumentBlockAddon</a></td></tr><tr><td align="center">Data Transformation Addon</td><td align="center"><p>This block is to produce a transformed result based on the data from the source</p><p>and filters blocks</p></td><td align="center"><a href="/pages/anVZ2yra5fH4tCsqNkCg">Data Transformation Addon</a></td></tr><tr><td align="center">IntegrationButtonBlock</td><td align="center">This block enable interaction with third-party data providers</td><td align="center"><a href="/pages/JzyxokhUbml73wXO0N78">IntegrationButton</a></td></tr><tr><td align="center">Global Events Reader Block</td><td align="center">This block subscribes to global topics and routes incoming events into policy branches</td><td align="center"><p><a href="/pages/qcyg0yIofZLDVRmYkodr">Global Events Reader</a></p><p><a href="/pages/qcyg0yIofZLDVRmYkodr">Block</a></p></td></tr><tr><td align="center">Global Events Writer Block</td><td align="center">This block publishes document references to one or more global Hedera topics</td><td align="center"><p><a href="/pages/QMTRaqcB5KArxDFfWCRd">Global Events Writer</a></p><p><a href="/pages/QMTRaqcB5KArxDFfWCRd">Block</a></p></td></tr><tr><td align="center">mathBlock</td><td align="center">This block defines calculations on document data in mathematical notation</td><td align="center"><a href="/pages/QNB5phDHMJxo5yXbSXFc">MathBlock</a></td></tr></tbody></table>


# InterfaceContainerBlock

### Properties

| Block Property | Definition                                                                        | Example Input                                   | Status |
| -------------- | --------------------------------------------------------------------------------- | ----------------------------------------------- | ------ |
| type           | A block which contains and organizes other blocks.                                | **InterfaceContainerBlock** (Can't be changed). |        |
| tag            | Unique name for the logic block.                                                  | installer\_header.                              |        |
| permissions    | Which entity has rights to interact at this part of the workflow.                 | Installer.                                      |        |
| defaultActive  | Shows whether this block is active at this time and whether it needs to be shown. | Checked or unchecked.                           |        |

{% hint style="info" %}
RefreshEvents are used to refreshing the UI, instead of "dependencies" property.
{% endhint %}

### **UI Properties**

| UI Property | Definition                                                                                                         |
| ----------- | ------------------------------------------------------------------------------------------------------------------ |
| Title       | Provides a title for the UI element.                                                                               |
| Type BLANK  | Does not contain any frame, will render all child elements one after the other.                                    |
| Type TABS   | A container which has a tab for each of the child element. It will render the first child element as type "blank". |

### Events

| Property Name | Name in JSON | Property Value                                                    | Value in JSON                          | Description                                                                                                                     |
| ------------- | ------------ | ----------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Event Type    | -            | <p>Input Event</p><p>Output Event</p>                             | -                                      | Type of the event - determines whether this is ingress or egress event for the current block.                                   |
| Source        | "source"     | Block tag(string)                                                 | "block\_tag"                           | The block which initiates the event.                                                                                            |
| Target        | "target"     | Block tag(string)                                                 | "block\_tag"                           | The block which receives the event.                                                                                             |
| Output Event  | "output"     | Event name(string)                                                | "event\_name"                          | Action or issue that caused the event.                                                                                          |
| Input Event   | "input"      | Event name(string)                                                | "event\_name"                          | Action which will be triggered by the event.                                                                                    |
| Event Actor   | "actor"      | <p>Event Initiator</p><p>Document Owner</p><p>Document Issuer</p> | <p>""</p><p>"owner"</p><p>"issuer"</p> | Allows to transfer control of the block (execution context) to another user. Empty field leaves control at the Event Initiator. |
| Disabled      | "disabled"   | True/False                                                        | true/false                             | Allows to disable the event without deleting it.                                                                                |

To know more information about events, please look at [Events](/guardian/standard-registry/policies/policy-creation/introduction/events)

### API Parameters

<mark style="color:blue;">`GET`</mark> `/policies/{policyID}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyID<mark style="color:red;">\*</mark> | String | Policy ID   |
| uuid<mark style="color:red;">\*</mark>     | String | block UUID  |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```javascript
    {
  "uiMetaData": {
    "type": "blank"
  },
  "id": "27c9f288-c4b4-4690-b3b9-9843cc90129f",
  "blockType": "interfaceContainerBlock",

}
```

{% endtab %}
{% endtabs %}


# PolicyRolesBlock

This block allows the user to select a role or a group.

### Properties

| Block Property    | Definition                                                                        | Example Input                                   | Status |
| ----------------- | --------------------------------------------------------------------------------- | ----------------------------------------------- | ------ |
| type              | A block which determines a role for the user.                                     | **PolicyRolesBlock** (Can't be changed).        |        |
| tag               | Unique name for the logic block.                                                  | choose\_role.                                   |        |
| permissions       | Which entity has rights to interact at this part of the workflow.                 | Installer.                                      |        |
| defaultActive     | Shows whether this block is active at this time and whether it needs to be shown. | Checked or unchecked.                           |        |
| roles             | Available roles from which the user can choose.                                   | Select the appropriate roles from the dropdown. |        |
| Available Roles   | list of roles for selected user                                                   | Checked or unchecked.                           |        |
| ·Available Groups | list of groups for selected user                                                  | Checked or unchecked.                           |        |

{% hint style="info" %}
**Note: ‘*****Available Groups*****’** option takes priority and thus, when set, causes the system to ignore **‘*****Available Roles*****’**.
{% endhint %}

{% hint style="info" %}
**Note:** Setting the Permissions property to ‘**No Role’** limits the visibility of this block to those users which have not yet selected a role or a group.
{% endhint %}

{% hint style="info" %}
RefreshEvents are used to refreshing the UI, instead of "dependencies" property.
{% endhint %}

### UI Properties

| UI Property | Definition                                   |
| ----------- | -------------------------------------------- |
| Title       | Provide the a title for the role selector.   |
| Description | Provide a description on the role selection. |

### Events

| Property Name | Name in JSON | Property Value                                                    | Value in JSON                          | Description                                                                                                                     |
| ------------- | ------------ | ----------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Event Type    | -            | <p>Input Event</p><p>Output Event</p>                             | -                                      | Type of the event - determines whether this is ingress or egress event for the current block.                                   |
| Source        | "source"     | Block tag(string)                                                 | "block\_tag"                           | The block which initiates the event.                                                                                            |
| Target        | "target"     | Block tag(string)                                                 | "block\_tag"                           | The block which receives the event.                                                                                             |
| Output Event  | "output"     | Event name(string)                                                | "event\_name"                          | Action or issue that caused the event.                                                                                          |
| Input Event   | "input"      | Event name(string)                                                | "event\_name"                          | Action which will be triggered by the event.                                                                                    |
| Event Actor   | "actor"      | <p>Event Initiator</p><p>Document Owner</p><p>Document Issuer</p> | <p>""</p><p>"owner"</p><p>"issuer"</p> | Allows to transfer control of the block (execution context) to another user. Empty field leaves control at the Event Initiator. |
| Disabled      | "disabled"   | True/False                                                        | true/false                             | Allows to disable the event without deleting it.                                                                                |

To know more information about events, please look at [Events](/guardian/standard-registry/policies/policy-creation/introduction/events).

### API Parameters

<mark style="color:blue;">`GET`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyId<mark style="color:red;">\*</mark> | String | PolicyID    |
| uuid<mark style="color:red;">\*</mark>     | String | Block UUID  |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```javascript
 {
  "roles": [],
  "groups": [
    "VVBs",
    "Project_Proponent"
  ],
  "groupMap": {
    "VVBs": {
      "groupAccessType": "Private",
      "groupRelationshipType": "Multiple"
    },
    "Project_Proponent": {
      "groupAccessType": "Private",
      "groupRelationshipType": "Single"
    }
  },
  "isMultipleGroups": true,
  "uiMetaData": {
    "title": "Roles",
    "description": "Choose Roles"
  }
}

```

{% endtab %}
{% endtabs %}

<mark style="color:green;">`POST`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyId<mark style="color:red;">\*</mark> | String | Policy ID   |
| uuid<mark style="color:red;">\*</mark>     | String | Block UUID  |

#### Request Body

| Name                                   | Type   | Description |
| -------------------------------------- | ------ | ----------- |
| role<mark style="color:red;">\*</mark> | String |             |
| invitation                             | String | Invite Code |
| Group                                  | String | Group Name  |


# InterfaceStepBlock

### Properties

| Block Property | Definition                                                                                                      | Example Input                              | Status |
| -------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ------ |
| type           | Similar to the **InterfaceContainer**Block, with the difference that it can only render a single child element. | **InterfaceStepBlock** (Can't be changed). |        |
| tag            | Unique name for the logic block.                                                                                | CSD01 Document.                            |        |
| permissions    | Which entity has rights to interact at this part of the workflow.                                               | Standard Registry.                         |        |
| defaultActive  | Shows whether this block is active at this time and whether it needs to be shown.                               | Checked or unchecked.                      |        |
| cyclic         | Go back one step to enable the creation of the previous object.                                                 | Checked or unchecked.                      |        |

{% hint style="info" %}
RefreshEvents are used to refreshing the UI, instead of "dependencies" property.
{% endhint %}

### Events

| Property Name | Name in JSON | Property Value                                                    | Value in JSON                                                                                                                   | Description |
| ------------- | ------------ | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| Event Type    | -            | <p>Input Event</p><p>Output Event</p>                             | Type of the event - determines whether this is ingress or egress event for the current block.                                   |             |
| Source        | "source"     | Block tag(string)                                                 | The block which initiates the event.                                                                                            |             |
| Target        | "target"     | Block tag(string)                                                 | The block which receives the event.                                                                                             |             |
| Output Event  | "output"     | Event name(string)                                                | Action or issue that caused the event.                                                                                          |             |
| Input Event   | "input"      | Event name(string)                                                | Action which will be triggered by the event.                                                                                    |             |
| Event Actor   | "actor"      | <p>Event Initiator</p><p>Document Owner</p><p>Document Issuer</p> | Allows to transfer control of the block (execution context) to another user. Empty field leaves control at the Event Initiator. |             |
| Disabled      | "disabled"   | True/False                                                        | Allows to disable the event without deleting it.                                                                                |             |

To know more information about events, please look at [Events](/guardian/standard-registry/policies/policy-creation/introduction/events).

### API Parameters

<mark style="color:blue;">`GET`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyId<mark style="color:red;">\*</mark> | String | Policy ID   |
| uuid<mark style="color:red;">\*</mark>     | String | Block UUID  |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```javascript
{
  "uiMetaData": {
    "type": "blank"
  },
  "index": 8,
  "id": "92fdc241-da15-46cb-9153-d223aeb61c5a",
  "blockType": "interfaceStepBlock",
  "blocks": [
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    {
      "uiMetaData": {
        "type": "tabs"
      },
      "content": "interfaceContainerBlock",
      "blockType": "interfaceContainerBlock",
      "id": "768d5fae-a907-4566-aa87-62f6929a03c7"
    },
    null,
    null,
    null,
    null,
    null
  ]
}

```

{% endtab %}
{% endtabs %}


# requestVCDocumentBlock

### Properties

| Block Property   | Definition                                                                                                                                                   | Example Input                                                                                                                | Status |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | ------ |
| type             | A type of the block which receives data in the format of a ‘credential subject’ part of a VC Document                                                        | **requestVCDocumentBlock** (Can't be changed).                                                                               |        |
| tag              | Unique name for the logic block.                                                                                                                             | add\_new\_installer\_request.                                                                                                |        |
| permissions      | Which entity has rights to interact at this part of the workflow.                                                                                            | Standard Registry.                                                                                                           |        |
| defaultActive    | Shows whether this block is active at this time and whether it needs to be shown.                                                                            | Checked or unchecked.                                                                                                        |        |
| schema           | Pre-configured schemas for the document relevant for policy action requests. Technically, it's the uuid of the schema, which will be used to build the form. | IRec-Application-Details (to be selected from the drop down of available schemas in your Guardian instance).                 |        |
| ID Type          | Select the type of ID that is populated in the ID field of the Verifiable Credential document.                                                               | Current Options are: DID (creates a new DID), UUID (creates a new UUID), and Owner (which uses the DID of the current user). |        |
| stop propagation | End processing here, don't pass control to the next block.                                                                                                   | Checked or Unchecked.                                                                                                        |        |

{% hint style="info" %}
RefreshEvents are used to refreshing the UI, instead of "dependencies" property.
{% endhint %}

### UI Properties

| UI Property          | Definition                                                                                                                                                                    |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Type                 | Style of the render of the form. It can be either a Page (the form is rendered as a page) or Dialogue (displays a button, which opens a dialogue with the form when clicked). |
| Title                | Provides the Page or Dialogue box a title.                                                                                                                                    |
| Description          | Provides the Page or Dialogue box a description.                                                                                                                              |
| hideWhenDiscontinued | Check if the button should be hidden when policy is discontinued                                                                                                              |
| Button Content       | Text to fill inside a button. Needs the Dialogue box to be selected from the "Type."                                                                                          |
| Dialogue Text        | Provides a tile inside the Dialogue box. Needs the dialogue box to be selected from the "Type."                                                                               |
| Dialogue Description | Provides a description inside the Dialogue box. Needs the dialogue box to be selected from the "Type."                                                                        |

### Events

| Property Name | Name in JSON | Property Value                                                    | Value in JSON                          | Description                                                                                                                     |
| ------------- | ------------ | ----------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Event Type    | -            | <p>Input Event</p><p>Output Event</p>                             | -                                      | Type of the event - determines whether this is ingress or egress event for the current block.                                   |
| Source        | "source"     | Block tag(string)                                                 | "block\_tag"                           | The block which initiates the event.                                                                                            |
| Target        | "target"     | Block tag(string)                                                 | "block\_tag"                           | The block which receives the event.                                                                                             |
| Output Event  | "output"     | Event name(string)                                                | "event\_name"                          | Action or issue that caused the event.                                                                                          |
| Input Event   | "input"      | Event name(string)                                                | "event\_name"                          | Action which will be triggered by the event.                                                                                    |
| Event Actor   | "actor"      | <p>Event Initiator</p><p>Document Owner</p><p>Document Issuer</p> | <p>""</p><p>"owner"</p><p>"issuer"</p> | Allows to transfer control of the block (execution context) to another user. Empty field leaves control at the Event Initiator. |
| Disabled      | "disabled"   | True/False                                                        | true/false                             | Allows to disable the event without deleting it.                                                                                |

To know more information about events, please look at [Events](/guardian/standard-registry/policies/policy-creation/introduction/events).

### API Parameters

<mark style="color:blue;">`GET`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| uuid<mark style="color:red;">\*</mark>     | String | Block ID    |
| policyId<mark style="color:red;">\*</mark> | String | Policy ID   |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```javascript
{
  "id": "ef2a7742-68d4-407f-ada7-14cdce80e24d",
  "blockType": "requestVcDocumentBlock",
  "schema": {
    "userDID": null,
    "_id": "63da04dd9670adb07f82b090",
    "id": "63da04dd9670adb07f82b090",
    "uuid": "6235abf8-6b48-4212-9ecc-c82bdf90405e",
    "hash": "",
    "name": "I-REC Facility & Device Reg",
    "description": "I-REC Facility & Device Reg",
    "entity": "VC",
    "status": "DRAFT",
    "readonly": false,
    "system": false,
    "active": false,
    "version": "",
    "creator": "did:hedera:testnet:9jShvNUsztLFbvEK442VPfkccLYW3F2oU3e6rCHzr7FT_0.0.3075949",
    "owner": "did:hedera:testnet:9jShvNUsztLFbvEK442VPfkccLYW3F2oU3e6rCHzr7FT_0.0.3075949",
    "topicId": "0.0.3120995",
    "messageId": "",
    "documentURL": "",
    "contextURL": "",
    "iri": "#6235abf8-6b48-4212-9ecc-c82bdf90405e",
    "document": {
      "$id": "#6235abf8-6b48-4212-9ecc-c82bdf90405e",
      "$comment": "{ \"@id\": \"#6235abf8-6b48-4212-9ecc-c82bdf90405e\", \"term\": \"6235abf8-6b48-4212-9ecc-c82bdf90405e\" }",
      "title": "I-REC Facility & Device Reg",
      "description": "I-REC Facility & Device Reg",
      "type": "object",
      "properties": {
        "@context": {
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          ],
          "readOnly": true
        },
        "id": {
          "type": "string",
          "readOnly": true
        },
        "field0": {
          "title": "Registrant Id",
          "description": "Registrant Id",
          "readOnly": false,
          "type": "string",
          "$comment": "{\"term\":\"field0\",\"@id\":\"https://www.schema.org/text\",\"orderPosition\":0}"
        },
        "policyId": {
          "title": "policyId",
          "description": "policyId",
          "readOnly": true,
          "type": "string",
          "$comment": "{\"term\":\"policyId\",\"@id\":\"https://www.schema.org/text\"}"
        },
        "ref": {
          "title": "ref",
          "description": "ref",
          "readOnly": true,
          "type": "string",
          "$comment": "{\"term\":\"ref\",\"@id\":\"https://www.schema.org/text\"}"
        },
        "field1": {
          "title": "Date",
          "description": "Date",
          "readOnly": false,
          "type": "string",
          "format": "date",
          "$comment": "{\"term\":\"field1\",\"@id\":\"https://www.schema.org/text\",\"orderPosition\":1}"
        },
        "field2": {
          "title": "Is the Registrant also the owner of the Device? (provide evidence) ",
          "description": "Is the Registrant also the owner of the Device? (provide evidence) ",
          "readOnly": false,
          "type": "string",
          "$comment": "{\"term\":\"field2\",\"@id\":\"https://www.schema.org/text\",\"orderPosition\":2}"
        },
        "field3": {
          "title": "Registrant Details",
          "description": "Registrant Details",
          "readOnly": false,
          "$ref": "#dee7e78b-44b8-4bb0-8be0-3a86bde752b2",
          "$comment": "{\"term\":\"field3\",\"@id\":\"#dee7e78b-44b8-4bb0-8be0-3a86bde752b2\",\"orderPosition\":3}"
        },
        "field4": {
          "title": "Production Device Details",
          "description": "Production Device Details",
          "readOnly": false,
          "$ref": "#b61a05c6-bb1a-4d7e-9299-c0932d8c0306",
          "$comment": "{\"term\":\"field4\",\"@id\":\"#b61a05c6-bb1a-4d7e-9299-c0932d8c0306\",\"orderPosition\":4}"
        },
        "field5": {
          "title": "Energy Sources",
          "description": "Energy Sources",
          "readOnly": false,
          "$ref": "#899e042e-dc62-4849-95dc-b982af558e6c",
          "$comment": "{\"term\":\"field5\",\"@id\":\"#899e042e-dc62-4849-95dc-b982af558e6c\",\"orderPosition\":5}"
        }
      },
      "required": [
        "@context",
        "type",
        "policyId",
        "field3",
        "field4",
        "field5"
      ],
      "additionalProperties": false,
      "$defs": {
        "#dee7e78b-44b8-4bb0-8be0-3a86bde752b2": {
          "$id": "#dee7e78b-44b8-4bb0-8be0-3a86bde752b2",
          "$comment": "{ \"@id\": \"#dee7e78b-44b8-4bb0-8be0-3a86bde752b2\", \"term\": \"dee7e78b-44b8-4bb0-8be0-3a86bde752b2\" }",
          "title": "Contact Details",
          "description": "Contact Details",
          "type": "object",
          "properties": {
            "@context": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              ],
              "readOnly": true
            },
            "type": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              ],
              "readOnly": true
            },
            "id": {
              "type": "string",
              "readOnly": true
            },
            "field0": {
              "title": "Organization Name",
              "description": "Organization Name",
              "readOnly": false,
              "type": "string",
              "$comment": "{\"term\":\"field0\",\"@id\":\"https://www.schema.org/text\",\"orderPosition\":0}"
            },
            "field1": {
              "title": "Address line 1",
              "description": "Address line 1",
              "readOnly": false,
              "type": "string",
              "$comment": "{\"term\":\"field1\",\"@id\":\"https://www.schema.org/text\",\"orderPosition\":1}"
            },
            "field2": {
              "title": "Address line 2",
              "description": "Address line 2",
              "readOnly": false,
              "type": "string",
              "$comment": "{\"term\":\"field2\",\"@id\":\"https://www.schema.org/text\",\"orderPosition\":2}"
            },
            "field3": {
              "title": "Address line 3",
              "description": "Address line 3",
              "readOnly": false,
              "type": "string",
              "$comment": "{\"term\":\"field3\",\"@id\":\"https://www.schema.org/text\",\"orderPosition\":3}"
            },
            "field4": {
              "title": "Postal code",
              "description": "Postal code",
              "readOnly": false,
              "type": "string",
              "$comment": "{\"term\":\"field4\",\"@id\":\"https://www.schema.org/text\",\"orderPosition\":4}"
            },
            "field5": {
              "title": "Country",
              "description": "Country",
              "readOnly": false,
              "type": "string",
              "$comment": "{\"term\":\"field5\",\"@id\":\"https://www.schema.org/text\",\"orderPosition\":5}"
            },
            "field6": {
              "title": "Contact person",
              "description": "Contact person",
              "readOnly": false,
              "type": "string",
              "$comment": "{\"term\":\"field6\",\"@id\":\"https://www.schema.org/text\",\"orderPosition\":6}"
.....
```

{% endtab %}
{% endtabs %}

<mark style="color:green;">`POST`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Request Body

| Name                                       | Type   | Description        |
| ------------------------------------------ | ------ | ------------------ |
| document<mark style="color:red;">\*</mark> | Object | Credential Subject |
| ref                                        | String | ID of linked VC    |


# sendToGuardianBlock

### 1. Properties

| Block Property   | Definition                                                                                                                                                                                                                                                                             | Example Input                                                                                                                                                                                                                   | Status |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| type             | A type of the block which can save a new or updated document.                                                                                                                                                                                                                          | **sendToGuardianBlock** (Can't be changed).                                                                                                                                                                                     |        |
| tag              | Unique name for the logic block.                                                                                                                                                                                                                                                       | save\_new\_approved\_document.                                                                                                                                                                                                  |        |
| permissions      | Which entity has rights to interact at this part of the workflow.                                                                                                                                                                                                                      | Standard Registry.                                                                                                                                                                                                              |        |
| defaultActive    | Shows whether this block is active at this time and whether it needs to be shown.                                                                                                                                                                                                      | Checked or unchecked.                                                                                                                                                                                                           |        |
| entityType       | Gives the document a label in the DB. Needed for filtering.                                                                                                                                                                                                                            | Installer.                                                                                                                                                                                                                      |        |
| stop Propagation | End processing here, don't pass control to the next block.                                                                                                                                                                                                                             | Checked or Unchecked.                                                                                                                                                                                                           |        |
| options          | List of attributes, which is added to the VC when it is being persistent. Can be used for more flexible filtration.                                                                                                                                                                    | <p>"name": "status"</p><p>"value": "Minted",</p>                                                                                                                                                                                |        |
| dataSource       | Where to send Data                                                                                                                                                                                                                                                                     | Database / Hedera Topic / Auto                                                                                                                                                                                                  |        |
| documentType     | Type of Document                                                                                                                                                                                                                                                                       | VC / DID / VP                                                                                                                                                                                                                   |        |
| topic            | Topic to send a document if 'dataSource' = 'Hedera Topic'                                                                                                                                                                                                                              | topic                                                                                                                                                                                                                           |        |
| topicOwner       | if ‘Hedera Topic’ is selected for the ‘Source Type’ a new optional property ‘Topic Owner’ appears which shows which field determines the User, who will own the topic of the document. This is because in ‘Hedera Topic’ only the template of Topic is selected, not the topic itself. | <p>Current User - user whose credentials were used to make the current post request</p><p>Document Owner - creator of the document (has default value)</p><p>Document Issuer - user which was the last to sign the document</p> |        |
| Memo             | if 'Data Source' is Hedera Topic, this field is enabled. This is used to customize the Memo field name                                                                                                                                                                                 | example memo ${document.id}                                                                                                                                                                                                     |        |
| skipSaveState    | Allows to skip save document state to prevent display the state in history. This property is visible only when block has Data Source : “Database” or “Auto”.                                                                                                                           | Checked or Unchecked                                                                                                                                                                                                            |        |

{% hint style="info" %}
**Note:**

‘**Force New Document**’ option has been removed as its usage resulted in the duplicate documents (with the same hashes) polluting the storage and causing confusion in the links (when building trust chain). For the cases when a new document needs to be created on the basis of the old one please use ’**reassigningBlock**’ which would create new *proof* and as result new document with the equivalent content but with a new hash.
{% endhint %}

### 2. Auto Property:

This option applied in most cases. When **Auto** is selected the system applies the following logic:

1\. If the hash of the new document (being saved) is different from the hash of the document then it is based on the message is sent to Hedera into the Policy Instance Topic.

2\. If the database contains another document with the same hash it gets refreshed, otherwise a new document is created in the database.

{% hint style="info" %}
RefreshEvents are used to refreshing the UI, instead of "dependencies" property.
{% endhint %}

### Events

| Property Name | Name in JSON | Property Value                                                    | Value in JSON                          | Description                                                                                                                     |
| ------------- | ------------ | ----------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Event Type    | -            | <p>Input Event</p><p>Output Event</p>                             | -                                      | Type of the event - determines whether this is ingress or egress event for the current block.                                   |
| Source        | "source"     | Block tag(string)                                                 | "block\_tag"                           | The block which initiates the event.                                                                                            |
| Target        | "target"     | Block tag(string)                                                 | "block\_tag"                           | The block which receives the event.                                                                                             |
| Output Event  | "output"     | Event name(string)                                                | "event\_name"                          | Action or issue that caused the event.                                                                                          |
| Input Event   | "input"      | Event name(string)                                                | "event\_name"                          | Action which will be triggered by the event.                                                                                    |
| Event Actor   | "actor"      | <p>Event Initiator</p><p>Document Owner</p><p>Document Issuer</p> | <p>""</p><p>"owner"</p><p>"issuer"</p> | Allows to transfer control of the block (execution context) to another user. Empty field leaves control at the Event Initiator. |
| Disabled      | "disabled"   | True/False                                                        | true/false                             | Allows to disable the event without deleting it.                                                                                |

To know more information about events, please look at [Events](/guardian/standard-registry/policies/policy-creation/introduction/events).


# reassigningBlock

### Properties

<table><thead><tr><th width="192.33333333333331">Block Property</th><th>Definition</th><th>Example Input</th><th>Status</th></tr></thead><tbody><tr><td>type</td><td>A block type which re-signs the document and change the user to document owner.</td><td><strong>reassigningBlock</strong> (Can't be changed).</td><td></td></tr><tr><td>tag</td><td>Unique name for the logic block.</td><td>wait_for_approval.</td><td></td></tr><tr><td>permissions</td><td>Which entity has rights to interact at this part of the workflow.</td><td>Installer.</td><td></td></tr><tr><td>defaultActive</td><td>Shows whether this block is active at this time and whether it needs to be shown.</td><td>Checked or unchecked.</td><td></td></tr><tr><td>dependencies</td><td>Establish workflow dependencies that need to be completed prior.</td><td>Select the appropriate block from the dropdown.</td><td><mark style="color:red;">Deprecated</mark></td></tr><tr><td>stop Propagation</td><td>End processing here, don't pass control to the next block.</td><td>Checked or Unchecked.</td><td></td></tr><tr><td>issuer</td><td>Person, who will be a Signer</td><td>not set - Current User<br>owner - document Owner<br>policyOwner - Policy Owner</td><td></td></tr><tr><td>actor</td><td>Person, who will be next Block Owner</td><td>not set - Current User<br>owner - document Owner<br>issuer - document Issuer</td><td></td></tr></tbody></table>

{% hint style="info" %}
RefreshEvents are used to refreshing the UI, instead of "dependencies" property.
{% endhint %}

### Events

| Property Name | Name in JSON | Property Value                                                    | Value in JSON                          | Description                                                                                                                     |
| ------------- | ------------ | ----------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Event Type    | -            | <p>Input Event</p><p>Output Event</p>                             | -                                      | Type of the event - determines whether this is ingress or egress event for the current block.                                   |
| Source        | "source"     | Block tag(string)                                                 | "block\_tag"                           | The block which initiates the event.                                                                                            |
| Target        | "target"     | Block tag(string)                                                 | "block\_tag"                           | The block which receives the event.                                                                                             |
| Output Event  | "output"     | Event name(string)                                                | "event\_name"                          | Action or issue that caused the event.                                                                                          |
| Input Event   | "input"      | Event name(string)                                                | "event\_name"                          | Action which will be triggered by the event.                                                                                    |
| Event Actor   | "actor"      | <p>Event Initiator</p><p>Document Owner</p><p>Document Issuer</p> | <p>""</p><p>"owner"</p><p>"issuer"</p> | Allows to transfer control of the block (execution context) to another user. Empty field leaves control at the Event Initiator. |
| Disabled      | "disabled"   | True/False                                                        | true/false                             | Allows to disable the event without deleting it.                                                                                |

To know more information about events, please look at [Events](/guardian/standard-registry/policies/policy-creation/introduction/events).


# InformationBlock

### Properties

<table><thead><tr><th width="192.33333333333331">Block Property</th><th>Definition</th><th>Example Input</th><th>Status</th></tr></thead><tbody><tr><td>type</td><td>A block type which can display a notification or a progress bar.</td><td><strong>InformationBlock</strong> (Can't be changed).</td><td></td></tr><tr><td>tag</td><td>Unique name for the logic block.</td><td>wait_for_approval.</td><td></td></tr><tr><td>permissions</td><td>Which entity has rights to interact at this part of the workflow.</td><td>Installer.</td><td></td></tr><tr><td>defaultActive</td><td>Shows whether this block is active at this time and whether it needs to be shown.</td><td>Checked or unchecked.</td><td></td></tr><tr><td>dependencies</td><td>Establish workflow dependencies that need to be completed prior.</td><td>Select the appropriate block from the dropdown.</td><td><mark style="color:red;">Deprecated</mark></td></tr><tr><td>stop Propagation</td><td>End processing here, don't pass control to the next block.</td><td>Checked or Unchecked.</td><td></td></tr></tbody></table>

{% hint style="info" %}
RefreshEvents are used to refreshing the UI, instead of "dependencies" property.
{% endhint %}

### UI Properties

| UI Property | Definition                                                                                            |
| ----------- | ----------------------------------------------------------------------------------------------------- |
| Type        | Select the type of UI element for notifications. It can be either a LOADER (progress bar) or TEXT box |
| Title       | Provides the Loader or Text box a title.                                                              |
| Description | Provides the Loader or Text box a description.                                                        |

### Events

| Property Name | Name in JSON | Property Value                                                    | Value in JSON                          | Description                                                                                                                     |
| ------------- | ------------ | ----------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Event Type    | -            | <p>Input Event</p><p>Output Event</p>                             | -                                      | Type of the event - determines whether this is ingress or egress event for the current block.                                   |
| Source        | "source"     | Block tag(string)                                                 | "block\_tag"                           | The block which initiates the event.                                                                                            |
| Target        | "target"     | Block tag(string)                                                 | "block\_tag"                           | The block which receives the event.                                                                                             |
| Output Event  | "output"     | Event name(string)                                                | "event\_name"                          | Action or issue that caused the event.                                                                                          |
| Input Event   | "input"      | Event name(string)                                                | "event\_name"                          | Action which will be triggered by the event.                                                                                    |
| Event Actor   | "actor"      | <p>Event Initiator</p><p>Document Owner</p><p>Document Issuer</p> | <p>""</p><p>"owner"</p><p>"issuer"</p> | Allows to transfer control of the block (execution context) to another user. Empty field leaves control at the Event Initiator. |
| Disabled      | "disabled"   | True/False                                                        | true/false                             | Allows to disable the event without deleting it.                                                                                |

To know more information about events, please look at [Events](/guardian/standard-registry/policies/policy-creation/introduction/events).

### API Parameters

<mark style="color:blue;">`GET`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyId<mark style="color:red;">\*</mark> | String | Policy ID   |
| uuid<mark style="color:red;">\*</mark>     | String | Block UUID  |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```javascript
{
  "uiMetaData": {
    "description": "The page will refresh automatically once the application is approved.",
    "type": "text",
    "title": "Submitted for Approval"
  }
}

```

{% endtab %}
{% endtabs %}


# InterfaceDocumentsSourceBlock

### Properties

<table><thead><tr><th width="179">Block Property</th><th>Definition</th><th>Example Input</th><th>Status</th></tr></thead><tbody><tr><td>type</td><td>A block type which outputs information from the DB as grid.</td><td><strong>InterfaceDocumentsSource Block</strong> (Can't be changed).</td><td></td></tr><tr><td>tag</td><td>Unique name for the logic block.</td><td>sensors_grid.</td><td></td></tr><tr><td>permissions</td><td>Which entity has rights to interact at this part of the workflow.</td><td>Installer.</td><td></td></tr><tr><td>defaultActive</td><td>Shows whether this block is active at this time and whether it needs to be shown.</td><td>Checked or unchecked.</td><td></td></tr><tr><td>dataType</td><td>Specify the table to request the data from.</td><td>Current options are: Verifiable Credential, DID, Approve, or Hedera.</td><td></td></tr></tbody></table>

{% hint style="info" %}
RefreshEvents are used to refreshing the UI, instead of "dependencies" property.
{% endhint %}

### UI Properties

<table><thead><tr><th width="312.6507787525413">UI Property</th><th>Definition</th></tr></thead><tbody><tr><td>Title</td><td>Type of the displayed value, possible options. Current options are: TEXT (ordinary text), BUTTON (a button), or BLOCK (a block embedded into the column).</td></tr><tr><td>Enable common sorting</td><td><ol><li>When it is true, user can sort grid data on UI side, or make POST request to interfaceSourceBlock with body ({ orderField: 'option.status', orderDirection: 'asc'}) to change sorting through the API</li><li>When it is false, user can set order to specific documentSourceAddon block by POST request with same body through the API</li></ol></td></tr><tr><td>Field Name</td><td>Object fields to retrieve the values from. Internal fields are separated by ".", access to array elements is via index. This is the field name.</td></tr><tr><td>Field Type</td><td>Current Options: TEXT, BUTTON, AND BLOCK.</td></tr><tr><td>Field Title</td><td>Title of the column.</td></tr><tr><td>Field Tooltip</td><td>Provide a tooltip for the field.</td></tr><tr><td>Field Cell Content</td><td>Content inside the cell.</td></tr><tr><td>Field UI Class</td><td>Arbitrary Class</td></tr><tr><td>Width</td><td>For example : 100px</td></tr><tr><td>Bind Group</td><td>If interfaceDocumentsSourceBlock has more than one documentsSourceAddon, then you can create different columns for each (names must be the same)</td></tr><tr><td>Bind Block</td><td>Specifying a "bindBlock" field would result in the display of the linked block in side the dialog.. Needs for the field type to be a BLOCK or BUTTON with the Action type as DIALOGUE.</td></tr><tr><td>Action</td><td>Needs for the field type to be a BUTTON. Specifies what action will happen when the button is clicked. Action options are currently: LINK to a URL or prompt a DIALOGUE box.</td></tr><tr><td>Dialogue Type</td><td>Currently only json type is supported. Needs for the field type to be a BUTTON and Action to be DIALOGUE.</td></tr><tr><td>Dialogue Content</td><td>Provide content for the dialogue box. Needs for the field type to be a BUTTON and Action to be DIALOGUE.</td></tr><tr><td>Dialogue Class</td><td>Dialog style. Needs for the field type to be a BUTTON and Action to be DIALOGUE.</td></tr></tbody></table>

### Events

| Property Name | Name in JSON | Property Value                                                    | Value in JSON                          | Description                                                                                                                     |
| ------------- | ------------ | ----------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Event Type    | -            | <p>Input Event</p><p>Output Event</p>                             | -                                      | Type of the event - determines whether this is ingress or egress event for the current block.                                   |
| Source        | "source"     | Block tag(string)                                                 | "block\_tag"                           | The block which initiates the event.                                                                                            |
| Target        | "target"     | Block tag(string)                                                 | "block\_tag"                           | The block which receives the event.                                                                                             |
| Output Event  | "output"     | Event name(string)                                                | "event\_name"                          | Action or issue that caused the event.                                                                                          |
| Input Event   | "input"      | Event name(string)                                                | "event\_name"                          | Action which will be triggered by the event.                                                                                    |
| Event Actor   | "actor"      | <p>Event Initiator</p><p>Document Owner</p><p>Document Issuer</p> | <p>""</p><p>"owner"</p><p>"issuer"</p> | Allows to transfer control of the block (execution context) to another user. Empty field leaves control at the Event Initiator. |
| Disabled      | "disabled"   | True/False                                                        | true/false                             | Allows to disable the event without deleting it.                                                                                |

To know more information about events, please look at [Events](/guardian/standard-registry/policies/policy-creation/introduction/events).

### API Parameters

<mark style="color:blue;">`GET`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyId<mark style="color:red;">\*</mark> | String | Policy ID   |
| uuid<mark style="color:red;">\*</mark>     | String | Block UUID  |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```
{
  "data": [
    {
      "_id": "63da084ddb84efbb04da4588",
      "dryRunId": "63da04e19670adb07f82b092",
      "dryRunClass": "VcDocumentCollection",
      "owner": "did:hedera:testnet:7Vn2KdgTZG2DZkz1x3naEJfazEACCEZGBkGLeUwrh45C_0.0.3075949",
      "hash": "29yk1PWG8h8euDCKFRcV9GXeXGCxhipyjaEnTaEw8wb9",
      "document": {
        "id": "urn:uuid:bd06ea41-9037-4294-b13d-f868563e30f1",
        "type": [
          "VerifiableCredential"
        ],
        "issuer": "did:hedera:testnet:7Vn2KdgTZG2DZkz1x3naEJfazEACCEZGBkGLeUwrh45C_0.0.3075949",
        "issuanceDate": "2023-02-01T06:35:57.132Z",
        "@context": [
          "https://www.w3.org/2018/credentials/v1"
        ],
        "credentialSubject": [
          {
            "field1": {
              "type": "bf7109c2-6ff4-47bb-a39d-02a0f11574b0",
              "@context": []
            },
            "field2": {
              "type": "dee7e78b-44b8-4bb0-8be0-3a86bde752b2",
              "@context": []
            },
            "field3": {
              "type": "86f9436f-82fd-48ce-bce8-37a5130263b0",
              "@context": []
            },
            "policyId": "63da04e19670adb07f82b092",
            "@context": [
              "schema#f6ab05cd-95a6-4465-8b3a-e1e87375fef9"
            ],
            "id": "did:hedera:testnet:7Vn2KdgTZG2DZkz1x3naEJfazEACCEZGBkGLeUwrh45C_0.0.3075949",
            "type": "f6ab05cd-95a6-4465-8b3a-e1e87375fef9"
          }
        ],
        "proof": {
          "type": "Ed25519Signature2018",
          "created": "2023-02-01T06:35:57Z",
          "verificationMethod": "did:hedera:testnet:7Vn2KdgTZG2DZkz1x3naEJfazEACCEZGBkGLeUwrh45C_0.0.3075949#did-root-key",
          "proofPurpose": "assertionMethod",
          "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..XUDlrhjJkXHgOIKVdGZETi3koGVRJM2elk70XKzRmCxVL8OyMEfhVyEz9c2z4L7I00dlH0nrZKoirtOdp0puAA"
        }
      },
      "createDate": "2023-02-01T06:35:57.508Z",
      "updateDate": "2023-02-01T06:35:57.508Z",
"created": "2023-02-01T06:35:57.508Z",
      "updated": "2023-02-01T06:35:57.508Z",
      "status": "NEW",
      "signature": 0,
      "type": "registrant",
      "policyId": "63da04e19670adb07f82b092",
      "tag": "create_application(db)",
      "messageId": "1675.233357483",
      "topicId": "0.0.1675233357271",
      "relationships": null,
"option": {
        "status": "Waiting for approval"
      },
      "comment": null,
      "assignedTo": null,
      "assignedToGroup": null,
      "hederaStatus": "ISSUE",
      "schema": "#f6ab05cd-95a6-4465-8b3a-e1e87375fef9",
      "accounts": {
        "default": "0.0.1675233350065"
      },
      "tokens": null,
      "uuid": "801f790a-404c-4869-ae1b-4e5fe1146783",
      "entity": "NONE",
      "iri": "801f790a-404c-4869-ae1b-4e5fe1146783",
      "readonly": false,
      "system": false,
      "active": false,
      "codeVersion": "1.0.0",
      "group": "8e58d3eb-9af5-4705-a9b3-
.....
```

{% endtab %}
{% endtabs %}

<mark style="color:green;">`POST`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyId<mark style="color:red;">\*</mark> | String | Policy ID   |
| uuid<mark style="color:red;">\*</mark>     | String | Block UUID  |

#### Request Body

| Name           | Type   | Description              |
| -------------- | ------ | ------------------------ |
| orderDirection | String | Order Direction ASC,DESC |
| orderField     | String | Order Field Path         |

### Path Parameters for Pagination and Filtration

#### With Child Blocks

InterfaceDocumentsSourceBlock can accept and pass-on query parameters to the child pagination and filtration add-ons.

**Pagination**

| Name         | Type   |
| ------------ | ------ |
| itemsPerPage | Number |
| page         | Number |

**Filtration**

| Name  | Type   | Description                               |
| ----- | ------ | ----------------------------------------- |
| key   | Number | ID or a tag of the filtration add-ons     |
| Value | String | the filtervalue for the Filtration add-on |

**Example:**

```
/api/v1/policies/<policyId>/blocks/<blockId>?itemsPerPage=20&page=0&Block_5=valuetofilterby
```

#### Without Child Blocks

| Name         | Description                         |
| ------------ | ----------------------------------- |
| filterByUUID | return document with specified uuid |

**Example:**

```
/api/v1/policies/<policyId>/blocks/<blockId>?itemsPerPage=20&page=0&<filterBlock id or tag>=<filterValue>&filterByUUID=<document uuid>
```


# paginationAddon

## Properties

| Block Property | Definition                                                                        | Example Input                                   |
| -------------- | --------------------------------------------------------------------------------- | ----------------------------------------------- |
| type           | A block type which adds pagination to the InterfaceDocumentSourceBlock if added   | **paginationAddon** (Can't be changed).         |
| tag            | Unique name for the logic block.                                                  |                                                 |
| permissions    | Which entity has rights to interact at this part of the workflow.                 | Installer                                       |
| defaultActive  | Shows whether this block is active at this time and whether it needs to be shown. | Checked or Unchecked                            |
| dependencies   | Establish workflow dependancies that need to be completed prior.                  | Select the appropriate block from the dropdown. |

## API Parameters

## Requests Block Data

<mark style="color:blue;">`GET`</mark> `/policies/{policyId}/blocks/{uuid}`

Requests Block Data

#### Path Parameters

| Name                                       | Type   | Description         |
| ------------------------------------------ | ------ | ------------------- |
| policyId<mark style="color:red;">\*</mark> | String | Selected policy ID  |
| uuid<mark style="color:red;">\*</mark>     | String | Selected Block UUID |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```
{
		  "size": 5,
		  "itemsPerPage": 10,
		  "page": 0
}
```

{% endtab %}
{% endtabs %}

## Requests Block Data by Tag

<mark style="color:blue;">`GET`</mark> `/policies/{policyId}/tag/{tag}/blocks`

Requests Block Data by Tag

#### Path Parameters

| Name                                       | Type   | Description                  |
| ------------------------------------------ | ------ | ---------------------------- |
| policyId<mark style="color:red;">\*</mark> | String | Selected Policy ID           |
| tag<mark style="color:red;">\*</mark>      | String | Tag from the selected policy |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```
{
		  "size": 5,
		  "itemsPerPage": 10,
		  "page": 0
}
```

{% endtab %}
{% endtabs %}

## Sends data to the specified block

<mark style="color:green;">`POST`</mark> `/policies/{policyId}/blocks/{uuid}`

Sends data to the specified block

#### Path Parameters

| Name                                       | Type   | Description         |
| ------------------------------------------ | ------ | ------------------- |
| policyId<mark style="color:red;">\*</mark> | String | Selected Policy ID  |
| uuid<mark style="color:red;">\*</mark>     | String | Selected Block UUID |

#### Request Body

| Name                               | Type   | Description                                  |
| ---------------------------------- | ------ | -------------------------------------------- |
| <mark style="color:red;">\*</mark> | Object | Object with the data to be sent to the block |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

{% endtab %}
{% endtabs %}

## Sends data to the specified block by tag

<mark style="color:green;">`POST`</mark> `/policies/{policyId}/tag/{tag}/blocks`

Sends data to the specified block

#### Path Parameters

| Name                                       | Type   | Description         |
| ------------------------------------------ | ------ | ------------------- |
| policyId<mark style="color:red;">\*</mark> | String | Selected Policy ID  |
| uuid<mark style="color:red;">\*</mark>     | String | Selected Block UUID |

#### Request Body

| Name                               | Type   | Description                                  |
| ---------------------------------- | ------ | -------------------------------------------- |
| <mark style="color:red;">\*</mark> | Object | Object with the data to be sent to the block |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

{% endtab %}
{% endtabs %}


# DocumentsSourceAddOn

{% hint style="info" %}
Note: This block is used for dropdown. You can add multiple blocks to 1 grid to combine different data.
{% endhint %}

### Properties

<table><thead><tr><th width="282.3333333333333">Block Property</th><th>Definition</th><th>Example Input</th><th>Status</th></tr></thead><tbody><tr><td>type</td><td>A block for searching VC, for grid</td><td><strong>DocumentsSourceAddOn Block</strong> (Can't be changed).</td><td></td></tr><tr><td>tag</td><td>Unique name for the logic block.</td><td>approve<em>d_documents_</em>grid_source</td><td></td></tr><tr><td>permissions</td><td>Which entity has rights to interact at this part of the workflow.</td><td>Installer.</td><td></td></tr><tr><td>defaultActive</td><td>Shows whether this block is active at this time and whether it needs to be shown.</td><td>Checked or unchecked.</td><td></td></tr><tr><td>dependencies</td><td>Automatic update. The block is automatically re-rendered if any of the linked components gets updated.</td><td>Select the appropriate block from the dropdown.</td><td></td></tr><tr><td>Data Type</td><td>Specify the table to request the data from.</td><td>Current options are: Verifiable Credential, DID, Approve, or Hedera.</td><td></td></tr><tr><td>Schema</td><td>Filters the VC according to the selected scheme</td><td>iRec Application Details (1.0.0) PUBLISHED</td><td></td></tr><tr><td>onlyOwnDocuments</td><td>When checked, filter out only VCs created by the user</td><td>checked or unchecked</td><td></td></tr><tr><td>onlyAssignDocuments</td><td>When checked, it filter only VCs assigned to the user</td><td>checked or unchecked</td><td></td></tr><tr><td>Order Field</td><td>name of the field</td><td>Source</td><td></td></tr><tr><td>Order Direction</td><td>Ascending or Descending direction of the order</td><td>ASC/DESC</td><td></td></tr></tbody></table>

{% hint style="info" %}
Note: If no Order Field is specified, but Order Direction is specified, then Order Field will be automatically filled = createDate and data will be sorted by createDate
{% endhint %}

### Filter Properties

| Filter Property | Definition                                                 | Example Input |
| --------------- | ---------------------------------------------------------- | ------------- |
| Field           | Name of the field to filter, it can be nested using "."    | option.status |
| Type            | Filter on the basis of type (Equal, Not Equal, In, Not In) | Equal         |
| Value           | The field by which to filter Value                         | Verified      |

### API Parameters

<mark style="color:green;">`POST`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyID<mark style="color:red;">\*</mark> | String | Policy ID   |
| uuid<mark style="color:red;">\*</mark>     | String | Block UUID  |

#### Request Body

| Name           | Type   | Description                |
| -------------- | ------ | -------------------------- |
| orderBy        | String | Order Field Path           |
| orderDirection | String | Order Direction, ASC, DESC |


# filtersAddOnBlock

{% hint style="info" %}
Note: This block is used for dropdown. You can add multiple blocks to 1 grid to combine different data.
{% endhint %}

### Properties

| Block Property | Definition                                                                                                                                       | Example Input                                                         |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- |
| type           | A block for providing dynamic filters to DocumentsSourceAddOn Block                                                                              | **filtersAddOnBlock** (Can't be changed).                             |
| tag            | Unique name for the logic block.                                                                                                                 | report\_\_by\_\_project                                               |
| permissions    | Which entity has rights to interact at this part of the workflow.                                                                                | Installer.                                                            |
| defaultActive  | Shows whether this block is active at this time and whether it needs to be shown.                                                                | Checked or unchecked.                                                 |
| dependencies   | Automatic update. The block is automatically re-rendered if any of the linked components gets updated.                                           | Select the appropriate block from the dropdown.                       |
| type           | Filter type, so far only Dropdown type - allows the user to select one of the available values.                                                  | The list of available values is provided by DocumentsSourceAddonBlock |
| canBeEmpty     | if true - if the filter is empty, then it is not taken into account when filtering. If false - then after filtering there will be an empty array | checked or unchecked                                                  |
| field          | the field by which the filtering will take place                                                                                                 | document.credentialSubject.0.ref                                      |
| optionName     | the field to be used as the label                                                                                                                | document.credentialSubject.0.id                                       |
| optionValue    | the field that will act as the value                                                                                                             | document.credentialSubject.0.id                                       |

### UI Properties

| Filter Property | Definition             | Example Input |
| --------------- | ---------------------- | ------------- |
| Title           | Filter title           | Filter1       |
| Button Context  | text inside the button | Project       |

### API Parameters

<mark style="color:blue;">`GET`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyID<mark style="color:red;">\*</mark> | String | Policy ID   |
| uuid                                       | String | Block UUID  |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```javascript
{
  "id": "a4b87158-7428-48ac-b69b-762f96777edc",
  "blockType": "filtersAddon",
  "type": "dropdown",
  "uiMetaData": {
    "options": [],
    "content": "Device"
  },
  "data": [
    {
      "name": "device1",
      "value": "did:hedera:testnet:EHXwuE486eSD4yGXr6qTNLstmb8H1B2Jn4kx3PeWZzjv_0.0.1675232535045"
    }
  ],
  "optionName": "document.credentialSubject.0.field4.field0",
  "optionValue": "document.credentialSubject.0.id",
  "filterValue": "did:hedera:testnet:EHXwuE486eSD4yGXr6qTNLstmb8H1B2Jn4kx3PeWZzjv_0.0.1675232535045"
}

```

{% endtab %}
{% endtabs %}

<mark style="color:green;">`POST`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyId<mark style="color:red;">\*</mark> | String | Policy ID   |
| uuid<mark style="color:red;">\*</mark>     | String | Block UUID  |

#### Request Body

| Name                                          | Type   | Description      |
| --------------------------------------------- | ------ | ---------------- |
| filterValue<mark style="color:red;">\*</mark> | String | New filter value |


# InterfaceActionBlock

### Properties

| Block Property   | Definition                                                                        | Example Input                                                                  | Status |
| ---------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------ |
| type             | A block to create custom actions.                                                 | **InterfaceActionBlock** (Can't be changed).                                   |        |
| tag              | Unique name for the logic block.                                                  | download\_config\_btn.                                                         |        |
| permissions      | Which entity has rights to interact at this part of the workflow.                 | Installer.                                                                     |        |
| defaultActive    | Shows whether this block is active at this time and whether it needs to be shown. | Checked or unchecked.                                                          |        |
| stop Propagation | End processing here, don't pass control to the next block.                        | Checked or unchecked.                                                          |        |
| type             | Specific the type of action workflow action block.                                | Current options are: SELECTOR (select an action) and DOWNLOAD (download files) |        |

### UI Properties

| UI Property    | Definition                                                                                                                                                                                                                                                                                      | Status |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| Title          | Provides the title.                                                                                                                                                                                                                                                                             |        |
| Field          | Provides the field name. Action workflow type needs to be SELECTOR.                                                                                                                                                                                                                             |        |
| Option Name    | Provides the name of the option. Action workflow type needs to be SELECTOR.                                                                                                                                                                                                                     |        |
| Option Value   | Provides the value of the option. Action workflow type needs to be SELECTOR.                                                                                                                                                                                                                    |        |
| UI Class       | Button style. Action workflow type needs to be SELECTOR.                                                                                                                                                                                                                                        |        |
| Button Content | Provide the content for the button. Action workflow type needs to be DOWNLOAD.                                                                                                                                                                                                                  |        |
| Schema         | Pre-configured schemas relevant for download to be selected from the drop down of available schemas in your Guardian instance. Only needed in the reference implementation of the Guardian because of the IoT Simulator that is generating MRV data. Action workflow type needs to be DOWNLOAD. |        |
| Target URL     | Set the target URL where the file should be stored. Only needed in the reference implementation of the Guardian because of the IoT Simulator that is generating MRV data. Action workflow type needs to be DOWNLOAD.                                                                            |        |
| User           | Action workflow type needs to be SELECTOR. It determines who will get update actions (Dependencies property in other blocks) and which user will be used in next Blocks. It can be "Current" or "Owner". "Current" - user under which the action is performed. "Owner" - document owner.        |        |
| Option Tag     | Name of the dynamic events                                                                                                                                                                                                                                                                      |        |

![](/files/8Col1pFQWF31XV2SsINo)

### Events

| Property Name | Name in JSON | Property Value                                                    | Value in JSON                          | Description                                                                                                                     |
| ------------- | ------------ | ----------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Event Type    | -            | <p>Input Event</p><p>Output Event</p>                             | -                                      | Type of the event - determines whether this is ingress or egress event for the current block.                                   |
| Source        | "source"     | Block tag(string)                                                 | "block\_tag"                           | The block which initiates the event.                                                                                            |
| Target        | "target"     | Block tag(string)                                                 | "block\_tag"                           | The block which receives the event.                                                                                             |
| Output Event  | "output"     | Event name(string)                                                | "event\_name"                          | Action or issue that caused the event.                                                                                          |
| Input Event   | "input"      | Event name(string)                                                | "event\_name"                          | Action which will be triggered by the event.                                                                                    |
| Event Actor   | "actor"      | <p>Event Initiator</p><p>Document Owner</p><p>Document Issuer</p> | <p>""</p><p>"owner"</p><p>"issuer"</p> | Allows to transfer control of the block (execution context) to another user. Empty field leaves control at the Event Initiator. |
| Disabled      | "disabled"   | True/False                                                        | true/false                             | Allows to disable the event without deleting it.                                                                                |

To know more information about events, please look at [Events](/guardian/standard-registry/policies/policy-creation/introduction/events).

### API Parameters

<mark style="color:blue;">`GET`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyId<mark style="color:red;">\*</mark> | String | Policy ID   |
| uuid<mark style="color:red;">\*</mark>     | String | Block UUID  |

{% tabs %}
{% tab title="200: OK Successful Operation" %}

```javascript
{
  "id": "448ff538-1c3b-45eb-a310-9414ae223b81",
  "blockType": "interfaceActionBlock",
  "type": "dropdown",
  "uiMetaData": {
    "options": [],
    "content": "VVB"
  },
  "name": "document.credentialSubject.0.field0",
  "value": "group",
  "field": "assignedToGroup",
  "options": [
    {
      "name": "1",
      "value": "6b3efd88-037c-4335-a4d1-02776e23973c"
    }
  ]
}

```

{% endtab %}
{% endtabs %}

<mark style="color:green;">`POST`</mark> `/policies/{policyId}/blocks/{uuid}`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| policyId<mark style="color:red;">\*</mark> | String | Policy ID   |
| uuid<mark style="color:red;">\*</mark>     | String | Block UUID  |

#### Request Body

| Name                                       | Type | Description |
| ------------------------------------------ | ---- | ----------- |
| document<mark style="color:red;">\*</mark> | VC   | VC Document |




---

[Next Page](/llms-full.txt/1)

