# 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](/docs/develop/guardian/readme-1)                                                            |
| Create and publish policies           | [Standard Registry](/docs/develop/guardian/platform/standard-registry)                                        |
| Digitize an environmental methodology | [Methodology Digitization Handbook](/docs/develop/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](/docs/develop/community-and-contributing/contributing)
* [Community Standards](/docs/develop/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](/docs/develop/guardian/architecture)
* Guide: [Methodology Digitization Handbook](/docs/develop/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](/docs/develop/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](/docs/develop/guardian/readme-1/getting-started/installation/building-from-source-and-run-using-docker)
2. [Pre-Build Containers](/docs/develop/guardian/readme-1/getting-started/installation/building-from-pre-build-containers)
3. [Manually](/docs/develop/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](/docs/develop/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](/docs/develop/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](/docs/develop/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 )](/docs/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 )](/docs/develop/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](/docs/develop/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>


# External Events

Guardian processes tasks asynchronously. As operations complete, it publishes events to an internal NATS message broker. External systems can subscribe to these events to build reliable, event-driven integrations without polling.

There are two ways to consume Guardian events:

* **Direct NATS subscription** — connect your own NATS client to the same broker and subscribe to subjects directly.
* **Application Events Module** — a standalone HTTP service (port 3012) that subscribes to NATS on your behalf and forwards events to registered webhooks or a streaming endpoint. See [Application Events Module](/docs/develop/guardian/architecture/external-events/monitoring-tools/application-events-module).

***

## Subscription Patterns

Guardian events use two NATS interaction patterns.

### Publish / Subscribe

Events with pattern type `publish` follow the standard pub/sub model. The same message is delivered to every active subscriber. If multiple subscribers are running, ensure your application handles potential duplicate delivery.

```js
import { connect, JSONCodec } from "nats";

(async () => {
  const nc = await connect({ servers: "localhost:4222" });
  const c = JSONCodec();

  const sub = nc.subscribe("external-events.token_minted");

  (async () => {
    for await (const m of sub) {
      console.log(`[${sub.getProcessed()}]`, c.decode(m.data));
    }
    console.log("subscription closed");
  })();
})();
```

For more details see the [NATS.js publish/subscribe documentation](https://github.com/nats-io/nats.js#publish-and-subscribe).

### Request / Reply

Events with pattern type `request` require the subscriber to reply. Guardian waits for your response before proceeding. If no listener is registered, or the listener responds with an error, Guardian continues with the original content unmodified.

This pattern is used for IPFS content interception hooks (e.g., encryption/decryption of content before upload or after read).

```js
import { connect, JSONCodec, StringCodec } from "nats";
import * as zlib from "zlib";

(async () => {
  const nc = await connect({ servers: "localhost:4222" });
  const c = JSONCodec();

  const interceptContent = (type, transformFn) => {
    const sub = nc.subscribe(type);
    console.log("Listening to IPFS event:", type);

    (async () => {
      for await (const m of sub) {
        try {
          const payload = c.decode(m.data);
          const transformed = transformFn(Buffer.from(payload.content, "base64"));
          const responseMessage = { body: transformed.toString("base64") };
          const compressed = zlib.deflateSync(JSON.stringify(responseMessage)).toString("binary");
          m.respond(StringCodec().encode(compressed));
        } catch (e) {
          // Respond with error to signal Guardian to skip interception for this message
          const compressed = zlib.deflateSync(JSON.stringify({ error: e.message })).toString("binary");
          m.respond(StringCodec().encode(compressed));
        }
      }
    })();
  };

  // Example: intercept IPFS uploads with a custom transform
  interceptContent("external-events.ipfs_before_upload_content", (buf) => {
    // encrypt or transform buf here, return Buffer
    return buf;
  });
})();
```

***

## Event Reference

### Core External Events

These events are published by Guardian's core services and represent the primary integration surface for external systems.

| Event Subject                                | Pattern   | Description                                                              |
| -------------------------------------------- | --------- | ------------------------------------------------------------------------ |
| `external-events.token_minted`               | publish   | A Hedera token was successfully minted                                   |
| `external-events.token_mint_complete`        | publish   | All token minting operations for a batch are complete                    |
| `external-events.error_logs`                 | publish   | An error was written to the Guardian logger service                      |
| `external-events.block_event`                | publish   | A policy block execution event occurred                                  |
| `external-events.block_complete`             | publish   | Full async execution chain for a block data call has settled             |
| `external-events.ipfs_added_file`            | publish   | A file was successfully added to IPFS                                    |
| `external-events.ipfs_before_upload_content` | request   | Hook: intercept and optionally transform content before IPFS upload      |
| `external-events.ipfs_after_read_content`    | request   | Hook: intercept and optionally transform content after reading from IPFS |
| `external-events.ipfs_loaded_file`           | subscribe | A file load from IPFS has completed                                      |

***

### `external-events.token_minted`

**Pattern:** publish

**Trigger:** Guardian successfully mints a Hedera token during policy execution.

**Payload:**

```json
{
  "tokenId": "0.0.1554488",
  "tokenValue": 10,
  "memo": "policy-mint-batch-1"
}
```

| Field        | Type   | Description                                               |
| ------------ | ------ | --------------------------------------------------------- |
| `tokenId`    | string | Hedera token identifier (`shard.realm.num`)               |
| `tokenValue` | number | Number of tokens minted in this operation                 |
| `memo`       | string | Optional memo string associated with the mint transaction |

***

### `external-events.token_mint_complete`

**Pattern:** publish

**Trigger:** All pending token minting operations in a batch have completed.

**Payload:**

```json
{
  "tokenValue": 10
}
```

| Field        | Type   | Description                                                    |
| ------------ | ------ | -------------------------------------------------------------- |
| `tokenValue` | number | Total number of tokens that were minted in the completed batch |

***

### `external-events.error_logs`

**Pattern:** publish

**Trigger:** An error is written to the Guardian logger service by any internal service.

**Payload:**

```json
{
  "message": "failed store/add invocation",
  "type": "error",
  "attributes": {
    "service": "guardian-service",
    "code": "IPFS_UPLOAD_FAILED"
  }
}
```

| Field        | Type   | Description                                                   |
| ------------ | ------ | ------------------------------------------------------------- |
| `message`    | string | Human-readable error description                              |
| `type`       | string | Severity or error category                                    |
| `attributes` | object | Additional contextual attributes from the originating service |

***

### `external-events.block_event`

**Pattern:** publish

**Trigger:** A policy block executes an action that produces an external event (e.g., a user submits a form, a document is set, a timer fires).

**Payload:**

```json
[
  {
    "type": "Set",
    "blockUUID": "37c1b465-5261-4626-8972-f367301974a1",
    "blockType": "requestVcDocumentBlock",
    "blockTag": "applicant_form",
    "userId": "did:hedera:testnet:zHcDLGFNymFAJiMBKnpbHDgjvTn6yZnwkPPeFhtJBECH_0.0.4532001",
    "data": {
      "documents": []
    }
  }
]
```

The payload is an array of block event objects. Each object has:

| Field       | Type   | Description                                                                                                                                                                             |
| ----------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`      | string | Event type — one of `Run`, `Set`, `TickAggregate`, `TickCron`, `DeleteMember`, `StartCron`, `StopCron`, `SignatureQuorumReachedEvent`, `SignatureSetInsufficientEvent`, `Step`, `Chunk` |
| `blockUUID` | string | Unique identifier of the block that produced this event                                                                                                                                 |
| `blockType` | string | The block's type name (e.g., `requestVcDocumentBlock`, `mintDocumentBlock`)                                                                                                             |
| `blockTag`  | string | The human-readable tag assigned to the block in the policy editor                                                                                                                       |
| `userId`    | string | Hedera DID of the user who triggered the block action                                                                                                                                   |
| `data`      | object | Block-specific payload; structure varies by block type                                                                                                                                  |

***

### `external-events.block_complete`

**Pattern:** publish

**Trigger:** Triggered when the full async execution chain (downstream blocks, IPFS uploads, Hedera message submissions) for a `SET_BLOCK_DATA` / `SET_BLOCK_DATA_BY_TAG` call has settled — success or failure. The `trackingId` field matches the value returned in the API response, so external systems can correlate the event with their request without polling.

**Payload:**

```json
{
  "trackingId": "550e8400-e29b-41d4-a716-446655440000",
  "blockType": "requestVcDocumentBlock",
  "blockTag": "request_vc",
  "blockId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
  "policyId": "6475a9e0-5f27-4ce3-b2f1-123456789abc",
  "userId": "did:hedera:testnet:z6MkHmF...",
  "status": "success",
  "timestamp": 1745123456789
}
```

| Field        | Type   | Description                                                       |
| ------------ | ------ | ----------------------------------------------------------------- |
| `trackingId` | string | UUID correlating this event to the originating API call           |
| `blockType`  | string | The block's type name                                             |
| `blockTag`   | string | The human-readable tag assigned to the block in the policy editor |
| `blockId`    | string | Unique identifier of the block                                    |
| `policyId`   | string | Identifier of the policy containing the block                     |
| `userId`     | string | Hedera DID of the user whose action triggered the chain           |
| `status`     | string | `success` or `failure`                                            |
| `timestamp`  | number | Unix epoch milliseconds when the chain settled                    |

***

### `external-events.ipfs_added_file`

**Pattern:** publish

**Trigger:** A file (document, schema, artifact) is successfully pinned to IPFS.

**Payload:**

```json
{
  "cid": "QmPs2ufs5VQPYGGX1ewEjKSR8zuEmeuWK4GBKFHZjXTCAQ",
  "url": "ipfs://QmPs2ufs5VQPYGGX1ewEjKSR8zuEmeuWK4GBKFHZjXTCAQ"
}
```

| Field | Type   | Description                     |
| ----- | ------ | ------------------------------- |
| `cid` | string | IPFS content identifier (CIDv0) |
| `url` | string | IPFS URI in `ipfs://` scheme    |

***

### `external-events.ipfs_before_upload_content`

**Pattern:** request/reply

**Trigger:** Guardian is about to upload content to IPFS. The content is delivered as a base64-encoded buffer.

**Payload received:**

```json
{
  "content": "<base64-encoded file content>"
}
```

**Expected reply:**

Return a zlib-deflated JSON object with the (optionally transformed) content:

```json
{
  "body": "<base64-encoded transformed content>"
}
```

To skip transformation and signal an error, respond with:

```json
{
  "error": "reason for skipping"
}
```

If no listener is registered, or the listener responds with an error, Guardian uploads the original content unchanged.

> **Note:** This event is a request/reply hook. It is not forwarded by the Application Events Module. Subscribe directly via NATS.

***

### `external-events.ipfs_after_read_content`

**Pattern:** request/reply

**Trigger:** Guardian has just read content from IPFS. Use this hook to decrypt or post-process content before Guardian consumes it.

**Payload received:**

```json
{
  "content": "<base64-encoded file content>"
}
```

**Expected reply:** Same structure as `ipfs_before_upload_content`. Return the transformed content or an error object.

> **Note:** This event is a request/reply hook. It is not forwarded by the Application Events Module. Subscribe directly via NATS.

***

### `external-events.ipfs_loaded_file`

**Pattern:** subscribe

**Trigger:** An asynchronous IPFS file load has completed (either successfully or with an error).

**Payload:**

```json
{
  "taskId": "be1c8bc2-c100-47c5-af48-46c10b5fde55",
  "fileContent": "<base64-encoded file content>",
  "error": null
}
```

| Field         | Type           | Description                                               |
| ------------- | -------------- | --------------------------------------------------------- |
| `taskId`      | string         | UUID correlating this result to the original load request |
| `fileContent` | string         | Base64-encoded file content; present on success           |
| `error`       | string \| null | Error message if the load failed; `null` on success       |

> **Note:** This event is not forwarded by the Application Events Module. Subscribe directly via NATS.

***

## Policy Engine Events

In addition to the core external events above, the Application Events Module also surfaces Guardian's internal policy coordination events. These are emitted on NATS subjects from the `PolicyEvents` and `PolicyEngineEvents` enumerations (e.g., `policy-event-policy-ready`, `policy-engine-event-publish-policies`).

These events are intended for advanced integrations that need to react to specific policy lifecycle transitions. They are available through the Application Events Module's streaming endpoint and webhook registration. Use **`GET /api/events`** on the Application Events Module to retrieve the complete list of exposed event subjects at runtime.

***

## Reference Implementation

A complete Node.js reference client demonstrating publish/subscribe and request/reply patterns (including IPFS content encryption) is available at:

[`common/src/mq/sample-external-client.ts`](https://github.com/hashgraph/guardian/blob/main/common/src/mq/sample-external-client.ts)


# Monitoring Tools

Guardian's monitoring tools provide infrastructure for external systems to observe and react to Guardian's internal event stream without requiring a direct NATS connection.

## Application Events Module

The [Application Events Module](/docs/develop/guardian/architecture/external-events/monitoring-tools/application-events-module) is a standalone HTTP service (port `3012`) that:

* Subscribes to all Guardian NATS event subjects on startup
* Exposes a REST API for registering and managing webhooks
* Delivers events to registered webhook URLs via HTTP POST
* Provides a streaming JSON endpoint for real-time event consumption

| Capability                        | Endpoint                    |
| --------------------------------- | --------------------------- |
| Register a webhook                | `POST /api/webhooks`        |
| List registered webhooks          | `GET /api/webhooks`         |
| Retrieve a single webhook         | `GET /api/webhooks/{id}`    |
| Update a webhook                  | `PUT /api/webhooks/{id}`    |
| Delete a webhook                  | `DELETE /api/webhooks/{id}` |
| List all available event subjects | `GET /api/events`           |
| Subscribe to live event stream    | `GET /api/events/subscribe` |
| Interactive API documentation     | `GET /api-docs`             |

For full details see [Application Events Module](/docs/develop/guardian/architecture/external-events/monitoring-tools/application-events-module).


# Application-events module

The Application Events Module is a standalone service that bridges Guardian's internal NATS event bus and external HTTP-based systems. It removes the need for external integrators to operate their own NATS client by providing:

* A **webhook registry** — register HTTP endpoints that receive event payloads via POST.
* A **streaming endpoint** — consume all events as a chunked JSON stream over HTTP.
* A **REST API** — manage webhook subscriptions and enumerate available event subjects.

The service runs on port `3012` by default. Interactive Swagger documentation is available at `http://localhost:3012/api-docs`.

***

## Architecture

```
Guardian Services
      │
      │ publishes events to
      ▼
   NATS Broker
      │
      │ subscribed by
      ▼
Application Events Module (port 3012)
      │
      ├──► Registered Webhooks (HTTP POST to your URLs)
      │
      └──► GET /api/events/subscribe (chunked JSON stream)
```

On startup the module:

1. Connects to MongoDB to load persisted webhook registrations.
2. Connects to the NATS broker and subscribes to all exposed event subjects.
3. For each received message, delivers the payload to all matching registered webhooks.

***

## Quickstart: Subscribe via Streaming Endpoint

The simplest way to consume events is the streaming endpoint. It returns a chunked JSON array that stays open as long as the connection is alive. Each element is a JSON object with the event subject and payload.

```bash
curl -N http://localhost:3012/api/events/subscribe
```

Example stream output:

```json
[
{"subject":"external-events.token_minted","payload":{"tokenId":"0.0.1554488","tokenValue":10}},
{"subject":"external-events.ipfs_added_file","payload":{"cid":"QmPs2ufs5VQPYGGX1ewEjKSR8zuEmeuWK4GBKFHZjXTCAQ","url":"ipfs://QmPs2ufs5VQPYGGX1ewEjKSR8zuEmeuWK4GBKFHZjXTCAQ"}},
```

The stream remains open. When the NATS connection closes, the array is terminated with `{"connection":"closed"}]`.

***

## Quickstart: Register a Webhook

**Step 1 — Retrieve the list of available event subjects:**

```bash
curl http://localhost:3012/api/events
```

Returns a JSON array of all event subject strings the module is currently forwarding, for example:

```json
[
  "external-events.token_minted",
  "external-events.token_mint_complete",
  "external-events.error_logs",
  "external-events.block_event",
  "external-events.ipfs_added_file",
  "policy-event-policy-ready",
  "policy-engine-event-publish-policies",
  ...
]
```

**Step 2 — Register a webhook for one or more event subjects:**

```bash
curl -X POST http://localhost:3012/api/webhooks \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-system.example.com/guardian-events",
    "events": [
      "external-events.token_minted",
      "external-events.block_event"
    ]
  }'
```

**Response `201 Created`:**

```json
{
  "id": "63e3e5e8a01b3c001234abcd"
}
```

**Step 3 — Receive events at your endpoint:**

When Guardian mints a token, your endpoint will receive an HTTP POST:

```json
{
  "tokenId": "0.0.1554488",
  "tokenValue": 10,
  "memo": "policy-mint"
}
```

***

## REST API Reference

### List Available Event Subjects

**`GET /api/events`**

Returns the complete list of NATS event subjects the module is currently subscribed to and will forward to webhooks or the streaming endpoint.

**Status:** `200 OK`

```json
[
  "external-events.token_minted",
  "external-events.token_mint_complete",
  "external-events.error_logs",
  "external-events.block_event",
  "external-events.ipfs_added_file",
  "policy-event-generate-policy",
  "policy-event-policy-ready",
  "..."
]
```

***

### Subscribe to Event Stream

**`GET /api/events/subscribe`**

Opens a persistent chunked HTTP response. Each chunk is a JSON object:

```json
{"subject": "<event-subject>", "payload": <event-payload>}
```

The response uses `Transfer-Encoding: chunked` and `Content-Type: application/json`. The stream starts with `[` and each element is separated by `,\n`. The array is closed when the NATS connection terminates.

**Status:** `200 OK` (streaming)

***

### Register a Webhook

**`POST /api/webhooks`**

Persists a new webhook registration. The module will HTTP POST the event payload to `url` whenever an event matching one of the registered `events` subjects is received.

**Request Body:**

```json
{
  "url": "https://your-system.example.com/events",
  "events": [
    "external-events.token_minted",
    "external-events.block_event"
  ]
}
```

| Field    | Type      | Required | Description                                                                     |
| -------- | --------- | -------- | ------------------------------------------------------------------------------- |
| `url`    | string    | Yes      | Publicly reachable HTTPS URL that accepts POST requests                         |
| `events` | string\[] | No       | List of event subjects to subscribe to; omit or pass `[]` to receive all events |

**Status:** `201 Created`

```json
{
  "id": "63e3e5e8a01b3c001234abcd"
}
```

| Field | Description                                          |
| ----- | ---------------------------------------------------- |
| `id`  | MongoDB ObjectId of the created webhook registration |

**Error Responses:**

| Status                      | Description                           |
| --------------------------- | ------------------------------------- |
| `400 Bad Request`           | Request body failed schema validation |
| `500 Internal Server Error` | Database write failed                 |

***

### List Registered Webhooks

**`GET /api/webhooks`**

Returns all persisted webhook registrations.

**Status:** `200 OK`

```json
[
  {
    "_id": "63e3e5e8a01b3c001234abcd",
    "url": "https://your-system.example.com/events",
    "events": ["external-events.token_minted"],
    "createdAt": "2026-04-06T08:00:00.000Z"
  }
]
```

***

### Retrieve a Webhook

**`GET /api/webhooks/{id}`**

Returns a single webhook registration by its MongoDB ObjectId.

**Path Parameters:**

| Parameter | Type   | Required | Description                     |
| --------- | ------ | -------- | ------------------------------- |
| `id`      | string | Yes      | MongoDB ObjectId of the webhook |

**Status:** `200 OK`

```json
{
  "_id": "63e3e5e8a01b3c001234abcd",
  "url": "https://your-system.example.com/events",
  "events": ["external-events.token_minted"],
  "createdAt": "2026-04-06T08:00:00.000Z"
}
```

**Error Responses:**

| Status          | Description                           |
| --------------- | ------------------------------------- |
| `404 Not Found` | No webhook exists with the given `id` |

***

### Update a Webhook

**`PUT /api/webhooks/{id}`**

Replaces the `url` and `events` fields of an existing webhook registration.

**Path Parameters:**

| Parameter | Type   | Required | Description                     |
| --------- | ------ | -------- | ------------------------------- |
| `id`      | string | Yes      | MongoDB ObjectId of the webhook |

**Request Body:**

```json
{
  "url": "https://your-system.example.com/new-endpoint",
  "events": [
    "external-events.token_minted",
    "external-events.token_mint_complete"
  ]
}
```

| Field    | Type      | Required | Description                    |
| -------- | --------- | -------- | ------------------------------ |
| `url`    | string    | Yes      | Updated destination URL        |
| `events` | string\[] | Yes      | Updated list of event subjects |

**Status:** `204 No Content`

**Error Responses:**

| Status            | Description                           |
| ----------------- | ------------------------------------- |
| `400 Bad Request` | Request body failed schema validation |
| `404 Not Found`   | No webhook exists with the given `id` |

***

### Delete a Webhook

**`DELETE /api/webhooks/{id}`**

Removes a webhook registration. The module will immediately stop forwarding events to the associated URL.

**Path Parameters:**

| Parameter | Type   | Required | Description                               |
| --------- | ------ | -------- | ----------------------------------------- |
| `id`      | string | Yes      | MongoDB ObjectId of the webhook to delete |

**Status:** `204 No Content`

***

## Available Event Subjects

The module exposes all events from three sources, minus internal request/reply hooks that are not suitable for HTTP delivery. Use `GET /api/events` to retrieve the live list. The categories are:

### Core External Events

| Subject                               | Description                      |
| ------------------------------------- | -------------------------------- |
| `external-events.token_minted`        | Token successfully minted        |
| `external-events.token_mint_complete` | Mint batch complete              |
| `external-events.error_logs`          | Error written to Guardian logger |
| `external-events.block_event`         | Policy block execution event     |
| `external-events.ipfs_added_file`     | File pinned to IPFS              |

> The following subjects are **excluded** from webhook/stream delivery because they are request/reply hooks requiring a synchronous NATS response: `external-events.ipfs_before_upload_content`, `external-events.ipfs_after_read_content`, `external-events.ipfs_loaded_file`

### Policy Coordination Events (selected)

| Subject                                | Description                                              |
| -------------------------------------- | -------------------------------------------------------- |
| `policy-event-generate-policy`         | Policy instance generation started                       |
| `policy-event-policy-ready`            | Policy instance is ready to serve requests               |
| `policy-event-policy-start-error`      | Policy failed to start                                   |
| `policy-event-delete-policy`           | Policy instance deleted                                  |
| `policy-event-block-update-broadcast`  | A block's state changed and UI should refresh            |
| `policy-event-mrv-data`                | MRV (measurement, reporting, verification) data received |
| `policy-event-record-update-broadcast` | Recording state changed                                  |

### Policy Engine Events (selected)

| Subject                                     | Description                                 |
| ------------------------------------------- | ------------------------------------------- |
| `policy-engine-event-create-policies`       | New policy created                          |
| `policy-engine-event-publish-policies`      | Policy published to Hedera                  |
| `policy-engine-event-dry-run-policies`      | Policy entered dry-run mode                 |
| `policy-engine-event-draft-policies`        | Policy reverted to draft                    |
| `policy-engine-event-delete-policy-async`   | Async policy deletion started               |
| `policy-engine-event-migrate-data`          | Policy data migration started               |
| `policy-engine-event-receive-external-data` | External data submitted to a running policy |

The full enumeration of all policy coordination and engine event subjects is defined in:

* [`interfaces/src/type/messages/policy-events.ts`](https://github.com/hashgraph/guardian/blob/main/interfaces/src/type/messages/policy-events.ts)
* [`interfaces/src/type/messages/policy-engine-events.ts`](https://github.com/hashgraph/guardian/blob/main/interfaces/src/type/messages/policy-engine-events.ts)

***

## Webhook Delivery

When an event is received on a subscribed NATS subject, the module iterates over all registered webhooks whose `events` array includes that subject and performs an HTTP POST to each registered URL.

* **Method:** `POST`
* **Content-Type:** `application/json`
* **Body:** The raw event payload (the object published on NATS)

Delivery is best-effort. If a webhook URL returns an error or times out, the failure is logged and the module moves on. There is no built-in retry mechanism — design your endpoint to be idempotent and implement your own retry handling if required.

***

## Configuration

The module is configured via environment variables. The key variables are:

| Variable      | Default | Description                                         |
| ------------- | ------- | --------------------------------------------------- |
| `PORT`        | `3012`  | HTTP port the service binds to                      |
| `MONGODB_URI` | —       | MongoDB connection string for webhook persistence   |
| `MQ_ADDRESS`  | —       | NATS broker address (e.g., `nats://localhost:4222`) |

Refer to the `application-events/.env.example` file in the repository for the complete list.


# 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>


# Workspace

The Workspace navigation section of the Guardian is where you build and manage everything that defines a policy — the schemas, policy logic, artifacts, tools, and modules you create and would take with you if you exported that policy.

### Reference

Workspace is organized into the building blocks of a policy, grouped under **Manage**:

* **Policies** — the set of rules, roles, workflows, and data-handling logic that governs how credentials, attestations, and reports are issued, verified, and used within a methodology or project.
* **Schemas** — structured data definitions that describe the format, attributes, and validation rules for the Verifiable Credentials and Presentations used within a policy.
* **Schema Rules** — validation logic that checks whether values entered into a schema's fields fall within acceptable ranges, using formulas or conditional (if/then/else) logic sourced from any field in the policy.
* **Schema Templates** — standalone entities that own a set of schemas and locking rules outside any policy, so a policy can apply a template, get policy-local copies of its schemas, and stay in sync as the template evolves.
* **Artifacts** — JSON files that represent a policy's or workflow's structure: rules, conditions, actions, parameters, and metadata.
* **Tools** — component-based, standardized pieces of policy logic, linked to policies by reference rather than fully embedded, with restricted editability and the ability to nest other Tools.
* **Modules** — encapsulated, independently-operable units of functionality that can be combined to build policies, workflows, and other system capabilities.
* **Formulas** — human-readable views of a policy's calculation logic, mapping the math variables in a formula back to the schema and document fields they represent.&#x20;

Each of these lives inside Workspace because it's something you directly author, edit, and own as part of building a policy — not something the platform manages on your behalf.

### Related

* [Policies](/docs/develop/guardian/workspace/policies)
* [Schemas](/docs/develop/guardian/workspace/schemas)
* [Tools](/docs/develop/guardian/workspace/tools)
* [Modules](/docs/develop/guardian/workspace/modules)
* [Artifacts](/docs/develop/guardian/workspace/artifacts)


# Policies

A policy collection of rules, roles, workflows, and data-handling logic that governs how documents (verified credentials), attestations, and reports are issued, verified, and used within an environmental methodology or project.

Policies act like a smart contract template for dMRV orchestrated off-chain by the Guardian where critical checkpoints are anchored to the Hedera network.

#### **Key Components of a Policy**

1. **Policy Roles & Permissions**
   * Define 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. **Policy 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

The following terms are used when creating Policies within the Guardian.

| 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.


# Policy Configurator

The Policy Configurator is the visual editing environment in which a Standard Registry builds and maintains a policy – the executable definition of a methodology, made up of blocks, roles, schemas, tokens, and the events that connect them.

## The Problem It Solves

A Guardian policy is ultimately a single large JSON configuration. Written by hand, that configuration is unforgiving: block tags must be unique, events must reference blocks that exist, every form block must point at a valid schema, and every mint block at a valid token. A misspelled tag or an orphaned event is not visible until the policy is run, and by then the failure surfaces as a broken workflow rather than an obvious typo.

The Configurator removes that class of error from the authoring process. It presents the policy as a navigable tree instead of nested braces, offers only the property values that are valid in context, and validates the whole configuration on demand – so structural mistakes are caught while editing rather than during a project's first submission.

It also solves a collaboration problem. Methodology experts, not developers, own the rules being digitized. A visual editor lets them read, review, and adjust a policy without reading JSON, while still producing exactly the same artifact a developer would.

## How It Works

The Configurator is opened from a policy in **Draft** status and edits that draft in place. Nothing is published to Hedera while editing; the draft is a working copy that can be revised freely until it is dry-run or published.

**A policy is a tree of blocks.** Every policy starts from a single container block and nests other blocks inside it. Each block has a type that determines what it does – rendering a form, requesting a signature, minting a token, calling an external service – and a set of properties that configure that behavior. The Configurator shows this hierarchy in the tree panel on the left; selecting a block loads its properties into the panel on the right.

**Blocks are addressed by tag.** Each block carries a tag that is unique within the policy. Tags are how blocks refer to each other: an event that moves a document from one step to the next names its source and target by tag, not by position in the tree. This is why moving a block within the tree does not break the workflow, and why renaming a tag does.

**Events connect blocks into a workflow.** The tree describes containment; events describe flow. An event fires when something happens in one block – a document is approved, a form is submitted, a timer elapses – and triggers an action in another. Together, the tree and the event graph are what turn a set of blocks into a working process.

**The same policy has three representations.** The Configurator can display the policy as a **tree**, as **JSON**, or as **YAML**, and switching between them converts the current state rather than opening a different document. The tree is the primary editing surface; the text views exist for bulk edits, diffing, and copying configuration between policies. An edit made in any view is an edit to the same underlying configuration.

**Reusable parts come from modules and tools.** Alongside blocks, the Configurator exposes modules and tools – self-contained fragments of policy logic that can be dropped into a policy and edited as a unit. Tools are published and versioned independently, so a policy can adopt a shared, already-validated piece of logic instead of duplicating it.

**Validation is explicit.** The Configurator can validate the entire configuration and report problems against the specific blocks that caused them. A policy that fails validation can still be saved as a draft; it cannot be meaningfully run.

**Editing ends at dry run or publish.** A dry run executes the policy in an isolated environment with virtual users and no Hedera transactions, so the workflow can be exercised before it becomes permanent. Publishing releases a numbered version of the policy to the public domain, at which point the configuration is frozen – further changes require a new version.

## Key Distinctions

**Policy Configurator vs. Policy Wizard.** The Wizard asks a series of questions and generates a policy configuration from the answers. It is a starting point that produces a conventional structure quickly, and its output is an ordinary draft policy. The Configurator is where that draft – or any other policy – is refined, extended, and maintained. The Wizard creates; the Configurator edits.

**Policy Configurator vs. the Policy APIs.** The APIs read and write the same policy configuration programmatically, and are the right tool for automation, CI pipelines, and migrations. The Configurator is the interactive equivalent, aimed at authoring and review rather than repeatable scripted changes.

**Configuring a policy vs. running one.** The Configurator defines what a policy will do. Executing it – registering users, submitting documents, minting tokens – happens in the policy's own interface once it is dry-run or published, and is not part of the Configurator.

## Related

* [Creating a Policy through Policy Configurator](/docs/develop/guardian/tutorials-and-examples/creating-a-policy-through-policy-configurator) – step-by-step construction of a policy in the editor
* [Getting Started with the Policy Workflows](/docs/develop/guardian/tutorials-and-examples/creating-a-policy-through-policy-configurator/getting-started-with-the-policy-workflows) – the first blocks of a working policy
* [Available Policy Workflow Blocks](/docs/develop/guardian/workspace/policies/policy-creation/introduction) – the specification for every block type and its properties


# 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](/docs/develop/guardian/workspace/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](/docs/develop/guardian/workspace/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](/docs/develop/guardian/workspace/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](/docs/develop/guardian/workspace/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](/docs/develop/guardian/workspace/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](/docs/develop/guardian/workspace/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](/docs/develop/guardian/workspace/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](/docs/develop/guardian/workspace/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](/docs/develop/guardian/workspace/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 |


# externalDataBlock

### Properties

| Block Property | Definition                                                                                                                     | Example Input                             | Status |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------- | ------ |
| type           | Receives data from the external source and passes them over the the next block.                                                | **externalDataBlock** (Can't be changed). |        |
| tag            | Unique name for the logic block.                                                                                               | mrv\_source.                              |        |
| 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.                     |        |
| entityType     | Specify the type of Entity this workflow block is for.                                                                         | MRV.                                      |        |
| schema         | Pre-configured schemas relevant for download to be selected from the drop down of available schemas in your Guardian instance. | MRV.                                      |        |

### 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](/docs/develop/guardian/workspace/policies/policy-creation/introduction/events).


# retirementDocumentBlock

### Properties

| Block Property   | Definition                                                                        | Example Input                                  | Status |
| ---------------- | --------------------------------------------------------------------------------- | ---------------------------------------------- | ------ |
| type             | Receives the VC from the previous block and retires based on the rule(s).         | **retirementDocumentBlock**(Can't be changed). |        |
| tag              | Unique name for the logic block.                                                  | retire\_token.                                 |        |
| 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.                          |        |
| stop Propagation | End processing here, don't pass control to the next block.                        | Checked or unchecked.                          |        |

### UI Properties

| UI Property | Definition                                                                                                                                                                   |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Token       | Select which token to retire. The token must exist in the Guardian instance.                                                                                                 |
| Rule        | Rules under which the number of tokens is calculated. Math operations are supported, e.g. the following will result in 20 tokens: data = { amount: 2 } rule = "amount \* 10" |

### 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](/docs/develop/guardian/workspace/policies/policy-creation/introduction/events).


# calculateContainerBlock & calculateMathAddOnBlock

## calculateContainerBlock

This Block accepts source VC as input and generates output as new VC document.

### Input Parameters:

#### inputSchema : source VC schema

#### inputFields : array of variables which would be taken from the source VC.

| Variable | Definition                               | Example of Input |
| -------- | ---------------------------------------- | ---------------- |
| name     | Refer to the specified field value       | field0           |
| title    | Title of the operation                   | Summary          |
| value    | Variable to store the value of the field | E0               |

```
"inputFields": [
                    {
                      "name": "field0",
                      "title": "Summary",
                      "value": "E0"
                    },
                ]
```

New variable "E0" would be created with a value set to one from the "field0" in the VC document.

{% hint style="info" %}
"title" is not a mandatory parameter. The value is set automatically as per the user convenience.
{% endhint %}

### Output Parameters

#### outputSchema : output VC schema

#### outputFields : array of variables of output VC, which will be the field with the values from the variables.

| Variable | Definition                                | Example of Input |
| -------- | ----------------------------------------- | ---------------- |
| name     | Variable that refers to specified field   | field0           |
| title    | Title of the operation                    | Summary          |
| value    | Points to the value of specified variable | E1               |

```
outputFields: [
                    {
                      "name": "field0",
                      "title": "Summary",
                      "value": "E1"
                    }
                ]
```

The output variable "field0" will contain the value from the variable "E1".

{% hint style="info" %}
"title" is not a mandatory parameter. The value is set automatically as per the user convenience.
{% endhint %}

## calculateMathAddonBlock

This Block performs mathematical calculations sequentially.

#### equations : array of formulas.

```
"equations": [
                    {
                      "variable": "E1",
                      "formula": "E0*10"
                    }
                ]
```

When above code is executed, a new variable, "E1" will be created which would contain the value of the calculation "E0\*10".

{% hint style="info" %}
Note: All the expressions available in [Math.js](https://mathjs.org/docs/) are supported by calculateMathAddOnBlock.
{% endhint %}

<table><thead><tr><th>Operator</th><th>Name</th><th>Syntax</th><th width="140">Associativity</th><th>Example</th><th>Result</th></tr></thead><tbody><tr><td><code>(</code>, <code>)</code></td><td>Grouping</td><td><code>(x)</code></td><td>None</td><td><code>2 * (3 + 4)</code></td><td><code>14</code></td></tr><tr><td><code>[</code>, <code>]</code></td><td>Matrix, Index</td><td><code>[...]</code></td><td>None</td><td><code>[[1,2],[3,4]]</code></td><td><code>[[1,2],[3,4]]</code></td></tr><tr><td><code>{</code>, <code>}</code></td><td>Object</td><td><code>{...}</code></td><td>None</td><td><code>{a: 1, b: 2}</code></td><td><code>{a: 1, b: 2}</code></td></tr><tr><td><code>,</code></td><td>Parameter separator</td><td><code>x, y</code></td><td>Left to right</td><td><code>max(2, 1, 5)</code></td><td><code>5</code></td></tr><tr><td><code>.</code></td><td>Property accessor</td><td><code>obj.prop</code></td><td>Left to right</td><td><code>obj={a: 12}; obj.a</code></td><td><code>12</code></td></tr><tr><td><code>;</code></td><td>Statement separator</td><td><code>x; y</code></td><td>Left to right</td><td><code>a=2; b=3; a*b</code></td><td><code>[6]</code></td></tr><tr><td><code>;</code></td><td>Row separator</td><td><code>[x; y]</code></td><td>Left to right</td><td><code>[1,2;3,4]</code></td><td><code>[[1,2],[3,4]]</code></td></tr><tr><td></td><td>Statement separator</td><td><code>x \n y</code></td><td>Left to right</td><td><code>a=2 \n b=3 \n a*b</code></td><td><code>[2,3,6]</code></td></tr><tr><td><code>+</code></td><td>Add</td><td><code>x + y</code></td><td>Left to right</td><td><code>4 + 5</code></td><td><code>9</code></td></tr><tr><td><code>+</code></td><td>Unary plus</td><td><code>+y</code></td><td>Right to left</td><td><code>+4</code></td><td><code>4</code></td></tr><tr><td><code>-</code></td><td>Subtract</td><td><code>x - y</code></td><td>Left to right</td><td><code>7 - 3</code></td><td><code>4</code></td></tr><tr><td><code>-</code></td><td>Unary minus</td><td><code>-y</code></td><td>Right to left</td><td><code>-4</code></td><td><code>-4</code></td></tr><tr><td><code>*</code></td><td>Multiply</td><td><code>x * y</code></td><td>Left to right</td><td><code>2 * 3</code></td><td><code>6</code></td></tr><tr><td><code>.*</code></td><td>Element-wise multiply</td><td><code>x .* y</code></td><td>Left to right</td><td><code>[1,2,3] .* [1,2,3]</code></td><td><code>[1,4,9]</code></td></tr><tr><td><code>/</code></td><td>Divide</td><td><code>x / y</code></td><td>Left to right</td><td><code>6 / 2</code></td><td><code>3</code></td></tr><tr><td><code>./</code></td><td>Element-wise divide</td><td><code>x ./ y</code></td><td>Left to right</td><td><code>[9,6,4] ./ [3,2,2]</code></td><td><code>[3,3,2]</code></td></tr><tr><td><code>%</code></td><td>Percentage</td><td><code>x%</code></td><td>None</td><td><code>8%</code></td><td><code>0.08</code></td></tr><tr><td><code>%</code></td><td>Addition with Percentage</td><td><code>x + y%</code></td><td>Left to right</td><td><code>100 + 3%</code></td><td><code>103</code></td></tr><tr><td><code>%</code></td><td>Subtraction with Percentage</td><td><code>x - y%</code></td><td>Left to right</td><td><code>100 - 3%</code></td><td><code>97</code></td></tr><tr><td><code>%</code> <code>mod</code></td><td>Modulus</td><td><code>x % y</code></td><td>Left to right</td><td><code>8 % 3</code></td><td><code>2</code></td></tr><tr><td><code>^</code></td><td>Power</td><td><code>x ^ y</code></td><td>Right to left</td><td><code>2 ^ 3</code></td><td><code>8</code></td></tr><tr><td><code>.^</code></td><td>Element-wise power</td><td><code>x .^ y</code></td><td>Right to left</td><td><code>[2,3] .^ [3,3]</code></td><td><code>[8,27]</code></td></tr><tr><td><code>'</code></td><td>Transpose</td><td><code>y'</code></td><td>Left to right</td><td><code>[[1,2],[3,4]]'</code></td><td><code>[[1,3],[2,4]]</code></td></tr><tr><td><code>!</code></td><td>Factorial</td><td><code>y!</code></td><td>Left to right</td><td><code>5!</code></td><td><code>120</code></td></tr><tr><td><code>&#x26;</code></td><td>Bitwise and</td><td><code>x &#x26; y</code></td><td>Left to right</td><td><code>5 &#x26; 3</code></td><td><code>1</code></td></tr><tr><td><code>~</code></td><td>Bitwise not</td><td><code>~x</code></td><td>Right to left</td><td><code>~2</code></td><td><code>-3</code></td></tr><tr><td><code>|</code></td><td>Bitwise or</td><td><code>x | y</code></td><td>Left to right</td><td><code>5 | 3</code></td><td><code>7</code></td></tr><tr><td><code>^|</code></td><td>Bitwise xor</td><td><code>x ^| y</code></td><td>Left to right</td><td><code>5 ^| 2</code></td><td><code>7</code></td></tr><tr><td><code>&#x3C;&#x3C;</code></td><td>Left shift</td><td><code>x &#x3C;&#x3C; y</code></td><td>Left to right</td><td><code>4 &#x3C;&#x3C; 1</code></td><td><code>8</code></td></tr><tr><td><code>>></code></td><td>Right arithmetic shift</td><td><code>x >> y</code></td><td>Left to right</td><td><code>8 >> 1</code></td><td><code>4</code></td></tr><tr><td><code>>>></code></td><td>Right logical shift</td><td><code>x >>> y</code></td><td>Left to right</td><td><code>-8 >>> 1</code></td><td><code>2147483644</code></td></tr><tr><td><code>and</code></td><td>Logical and</td><td><code>x and y</code></td><td>Left to right</td><td><code>true and false</code></td><td><code>false</code></td></tr><tr><td><code>not</code></td><td>Logical not</td><td><code>not y</code></td><td>Right to left</td><td><code>not true</code></td><td><code>false</code></td></tr><tr><td><code>or</code></td><td>Logical or</td><td><code>x or y</code></td><td>Left to right</td><td><code>true or false</code></td><td><code>true</code></td></tr><tr><td><code>xor</code></td><td>Logical xor</td><td><code>x xor y</code></td><td>Left to right</td><td><code>true xor true</code></td><td><code>false</code></td></tr><tr><td><code>=</code></td><td>Assignment</td><td><code>x = y</code></td><td>Right to left</td><td><code>a = 5</code></td><td><code>5</code></td></tr><tr><td><code>?</code> <code>:</code></td><td>Conditional expression</td><td><code>x ? y : z</code></td><td>Right to left</td><td><code>15 > 100 ? 1 : -1</code></td><td><code>-1</code></td></tr><tr><td><code>:</code></td><td>Range</td><td><code>x : y</code></td><td>Right to left</td><td><code>1:4</code></td><td><code>[1,2,3,4]</code></td></tr><tr><td><code>to</code>, <code>in</code></td><td>Unit conversion</td><td><code>x to y</code></td><td>Left to right</td><td><code>2 inch to cm</code></td><td><code>5.08 cm</code></td></tr><tr><td><code>==</code></td><td>Equal</td><td><code>x == y</code></td><td>Left to right</td><td><code>2 == 4 - 2</code></td><td><code>true</code></td></tr><tr><td><code>!=</code></td><td>Unequal</td><td><code>x != y</code></td><td>Left to right</td><td><code>2 != 3</code></td><td><code>true</code></td></tr><tr><td><code>&#x3C;</code></td><td>Smaller</td><td><code>x &#x3C; y</code></td><td>Left to right</td><td><code>2 &#x3C; 3</code></td><td><code>true</code></td></tr><tr><td><code>></code></td><td>Larger</td><td><code>x > y</code></td><td>Left to right</td><td><code>2 > 3</code></td><td><code>false</code></td></tr><tr><td><code>&#x3C;=</code></td><td>Smallereq</td><td><code>x &#x3C;= y</code></td><td>Left to right</td><td><code>4 &#x3C;= 3</code></td><td><code>false</code></td></tr><tr><td><code>>=</code></td><td>Largereq</td><td><code>x >= y</code></td><td>Left to right</td><td><code>2 + 4 >= 6</code></td><td><code>true</code></td></tr></tbody></table>

### Example

In the input VC is { "field0" : 5 }

```
		calculateContainerBlock:
			"inputFields": [
				{
				  "name": "field0",
				  "value": "E0"
				}
			]
			"outputFields": [
				{
				  "name": "field0",
				  "value": "E1"
				}
			]
		calculateMathAddon
			"equations": [
				{
				  "variable": "E1",
				  "formula": "E0*10"
				}
			]
```

Then

1. input VC variable "E0" will contain 5 (eg. "E0" = 5)
2. When executed a new variable "E1" will be created with the value "E1" = E0\*10 = 5 \* 10 = 50
3. In the output VC there will be "E1" variable
4. The result will be VC = { "field0" : 50 }


# reportBlock & reportItemBlock

## reportBlock

### 1. Properties

| Block Property | Definition                                                                        | Example Input                      | Status |
| -------------- | --------------------------------------------------------------------------------- | ---------------------------------- | ------ |
| type           | Type of workflow logic                                                            | **reportBlock**(Can't be changed). |        |
| tag            | Unique name for the logic block.                                                  | report.                            |        |
| 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.              |        |

### 2. Impacts Section

We have added new Impacts Section to display Primary/Secondary Impacts token details in Trustchain:

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

In the case when multiple linked mint blocks are used then the system displays all linked VPs as shown below:

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

#### 2.1 Data Format:

Ingress Document has following sections:

| Document Type         | Description                                                   |
| --------------------- | ------------------------------------------------------------- |
| vpDocument            | VP document found based on its hash                           |
| vcDocument            | VC document found based on its hash                           |
| impacts (new)         | array of Impacts (VCs) if exist                               |
| mintDocument          | VC document describing the mint                               |
| policyDocument        | VC document describing the policy                             |
| policyCreatorDocument | VC document describing the Standard Registry                  |
| documents             | collection of VC documents retrieved from the reportItemBlock |
| additionalDocuments   | array of VPs linked with the selected document                |

### 3. Token Transfer Section

Token transfer, which shows how much tokens is already transferred (will display only when transfer is needed)

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

### 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](/docs/develop/guardian/workspace/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
{
  "hash": "BV4VxNEGvBjodqZ6KWCoV6r4xks4LYSGu8mjWyXLLX52",
  "data": {
    "vpDocument": {
      "type": "VP",
      "title": "Verifiable Presentation",
      "tag": "mint_token",
      "hash": "BV4VxNEGvBjodqZ6KWCoV6r4xks4LYSGu8mjWyXLLX52",
      "issuer": "did:hedera:testnet:7Q9aPi8rEhceMGMqviCdya9APf515YVbtiyjHrHYPh5N_0.0.3075949",
      "username": "Virtual User 1",
      "document": {
        "_id": "63da2203db84efbb04da45a7",
        "dryRunId": "63da04e19670adb07f82b092",
        "dryRunClass": "VpDocumentCollection",
        "owner": "did:hedera:testnet:7Q9aPi8rEhceMGMqviCdya9APf515YVbtiyjHrHYPh5N_0.0.3075949",
        "hash": "BV4VxNEGvBjodqZ6KWCoV6r4xks4LYSGu8mjWyXLLX52",
        "document": {
          "id": "urn:uuid:0bb9966d-bbce-4e7d-a943-21c7d6283adc",
          "type": [
            "VerifiablePresentation"
          ],
          "@context": [
            "https://www.w3.org/2018/credentials/v1"
          ],
          "verifiableCredential": [
            {
              "id": "urn:uuid:7aeb978a-01bf-4ceb-be52-33997832e32d",
              "type": [
                "VerifiableCredential"
              ],
              "issuer": "did:hedera:testnet:9jShvNUsztLFbvEK442VPfkccLYW3F2oU3e6rCHzr7FT_0.0.3075949",
              "issuanceDate": "2023-02-01T08:25:38.804Z",
              "@context": [
                "https://www.w3.org/2018/credentials/v1"
              ],
              "credentialSubject": [
                {
                  "field0": "did:hedera:testnet:7Q9aPi8rEhceMGMqviCdya9APf515YVbtiyjHrHYPh5N_0.0.3075949",
                  "field1": "did:hedera:testnet:EHXwuE486eSD4yGXr6qTNLstmb8H1B2Jn4kx3PeWZzjv_0.0.1675232535045",
                  "field2": {
                    "field0": "Organization Name",
                    "type": "dee7e78b-44b8-4bb0-8be0-3a86bde752b2",
                    "@context": []
                  },
                  "field3": {
                    "field0": "device1",
                    "type": "b61a05c6-bb1a-4d7e-9299-c0932d8c0306",
                    "@context": []
                  },
                  "field6": "2023-02-01",
                  "field7": 1,
                  "field8": "2023-02-01",
                  "field17": "StandardRegistry",
                  "field18": "0.0.3075944",
                  "policyId": "63da04e19670adb07f82b092",
                  "ref": 
"did:hedera:testnet:EHXwuE486eSD4yGXr6qTNLstmb8H1B2Jn4kx3PeWZzjv_0.0.1675232535045",
                  "@context": [
                    "schema#80b8a663-8dec-411f-83fd-6e4cb7170427"
                  ],
                  "id": "urn:uuid:bdc30a12-443f-43a1-b1ff-05fdb4d39017",
                  "type": "80b8a663-8dec-411f-83fd-6e4cb7170427"
                }
              ],
              "proof": {
                "type": "Ed25519Signature2018",
                "created": "2023-02-01T08:25:38Z",
                "verificationMethod": "did:hedera:testnet:9jShvNUsztLFbvEK442VPfkccLYW3F2oU3e6rCHzr7FT_0.0.3075949#did-root-key",
                "proofPurpose": "assertionMethod",
                "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..hcXXdjwaicZzXlUraPIaQqEpMkt9tRYJWAEMX8j8ipXUcrh1dgTDeHxHmVfxOrpOaxqgoo2Sf2VltQi8FRjvBA"
              }
            },
            {
              "id": "urn:uuid:c6ae4294-bd77-43ec-9389-f0c1a9bbc830",
              "type": [
                "VerifiableCredential"
              ],
              "issuer": "did:hedera:testnet:9jShvNUsztLFbvEK442VPfkccLYW3F2oU3e6rCHzr7FT_0.0.3075949",
              "issuanceDate": "2023-02-01T08:25:38.920Z",
              "@context": [
                "https://www.w3.org/2018/credentials/v1"
              ],
              "credentialSubject": [
                {
                  "date": "2023-02-01T08:25:38.917Z",
                  "tokenId": "0.0.3120996",
                  "amount": "1",
                  "@context": [
                    "ipfs://bafkreib67gunqam5jcv6xx3ioapfzyrnvte5wvpmcq56emso5acckercae"
                  ],
                  "type": "MintToken"
                }
              ],
              "proof": {
                "type": "Ed25519Signature2018",
                "created": "2023-02-01T08:25:38Z",
                "verificationMethod": 
.....
```

{% 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 | VP Hash     |

## reportItemBlock

### Properties

| Block Property  | Definition                                                                                                                                                                              | Example Input                                                                                                                                                                                                                                               |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Title           | Title of the element                                                                                                                                                                    | Report                                                                                                                                                                                                                                                      |
| Description     | Description of the element                                                                                                                                                              | Reporting                                                                                                                                                                                                                                                   |
| Visibility      | Visibility of the element. False if there is a need to build a chain of elements which must not be shown                                                                                | False                                                                                                                                                                                                                                                       |
| Multiple        | which allows store multiple documents in Report Item                                                                                                                                    | True                                                                                                                                                                                                                                                        |
| Filters         | Array of filters for the VC for this element                                                                                                                                            | <p>"filters": \[</p><p>{</p><p>"field": "document.id", "value": "actionId", "typeValue": "variable", "type": "equal"</p><p>},</p><p>{</p><p>"typeValue": "value",</p><p>"field": "type",</p><p>"type": "equal",</p><p>"value": "report"</p><p>}</p><p>]</p> |
| Dynamic Filters | We can set “Field Path” (in current Report Item Document\[s]), “Next Item Field Path” and “Type” (Filter Type) to filter documents in Report Items dynamically directly in trust chain. | Type                                                                                                                                                                                                                                                        |
| Variables       | List of common variables. It gets filled in in the process of the transition from one reportItemBlock to the next                                                                       | <p>"variables": \[</p><p>{</p><p>"value":"document.credentialSubject.0.ref",</p><p>"name": "projectId"</p><p>}</p><p>]</p>                                                                                                                                  |

A new variable projectId will be created which would be assigned the value from document.credentialSubject.0.ref.


# switchBlock

### Properties

| Block Property     | Definition                                                                        | Example Input                                                                                                                                                                          | Status |
| ------------------ | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| tag                | Unique name for the logic Block.                                                  | **switchBlock**                                                                                                                                                                        |        |
| 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                                                                                                                                                                   |        |
| On errors          | Called if the system error occurs in the Block                                    | <ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul>                                                                                                         |        |
| stop Propagation   | End processing here, don't pass control to the next block.                        | Checked or Unchecked                                                                                                                                                                   |        |
| Execution Flow     | Flow of Execution                                                                 | <ol><li>First True - only the ‘branch’ under the first ‘true’ condition gets executed.</li><li>2. All True - branches under all conditions evaluated as ‘true’ get executed.</li></ol> |        |
| Condition(i)       | number of the condition                                                           | if (field(0))>1                                                                                                                                                                        |        |
| Condition Type     | Type of the condition                                                             | Equal - resolves as true if the condition is true - Not Equal - resolved as true if the condition is false - Unconditional - always true                                               |        |
| Condition (String) | condition expression which can contain math formulas                              | field0 > 0                                                                                                                                                                             |        |
| Actor              | the permissions/role context of the execution of the next block                   | Current User - user under whom the condition is evaluated - Document Owner - the creator of the document - Document Issuer - the signator of the document                              |        |
| Condition Tag      | The name of the dynamic events to use                                             | Condition 1                                                                                                                                                                            |        |

![](/files/huuq8zrGHki593hnoRxH)

### 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](/docs/develop/guardian/workspace/policies/policy-creation/introduction/events).


# aggregateDocumentBlock

### Properties

Input - a document or an array of documents which will be aggregated

Output - an array of documents, after the reporting period expired or the condition is met

| Block Property   | Definition                                                                                  | Example Input                                                                  | Status |
| ---------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------ |
| tag              | Unique name for the logic block.                                                            | **aggregateDocumentBlock**                                                     |        |
| 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.                                                          |        |
| On errors        | Called if the system error occurs in the Block                                              | <ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul> |        |
| stop Propagation | End processing here, don't pass control to the next block.                                  | Checked or unchecked.                                                          |        |
| GroupByFields    | We can set additional fields to group documents. Also documents are always grouped by user. | Field Path                                                                     |        |
| AggregateType    | Type of Aggregate                                                                           | <ul><li>Cumulative Dimension</li><li>Period</li></ul>                          |        |

```
If ‘Aggregate Type’ = ‘Cumulative Dimension’
			Expressions - calculated variables which help to ease the work with Condition and enable complex calculations
				Expression (i)
					Variable Name (string) - name of the variable
					Variable Value (string) - formula for calculating of the value of the variable
			Condition (string) - condition expression which can contain math formulas
		
If ‘Aggregate Type’ = ‘Period’
			Timer - timer object to track the aggregation period (launched separately)
			(Please note that this functionality will change in the near future)

			Empty Data - if this parameter is set to true the timer gets triggered even if there were no data
```

### 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](/docs/develop/guardian/workspace/policies/policy-creation/introduction/events).


# TimerBlock

### Properties

Input - document which is needed to start the timer for different users separately.

| Block Property   | Definition                                                                        | Example Input                                                                                                                                                                                                                                                                                                                      | Status |
| ---------------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| tag              | Unique name for the logic block.                                                  | **timerBlock**                                                                                                                                                                                                                                                                                                                     |        |
| 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.                                                                                                                                                                                                                                                                                                              |        |
| On errors        | Called if the system error occurs in the Block                                    | <ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul>                                                                                                                                                                                                                                                     |        |
| stop Propagation | End processing here, don't pass control to the next block.                        | Checked or unchecked.                                                                                                                                                                                                                                                                                                              |        |
| Start Date       | date/time to start the timer                                                      | 16-05-2022 16:00 (UTC+04:00)                                                                                                                                                                                                                                                                                                       |        |
| End Date         | date/time to stop the timer                                                       | 16-05-2022 16:00 (UTC+04:00)                                                                                                                                                                                                                                                                                                       |        |
| Period           | specification of the period which timer triggers (starting from the Start Date)   | <p>Yearly</p><p>Monthly</p><p>Weekly</p><p>Daily</p><p>Hourly</p><p>Custom - advanced period</p><p>configuration</p><p>If ‘Period’ = ‘Custom’<br>Mask - cron mask for timer (example: <a href="https://crontab.guru/"><https://crontab.guru/></a>)<br>Interval (number) - trigger timer on every tick<br>(e.g. every two days)</p> |        |
| Custom Period    | open dialogue window to set Mask and Interval                                     | 0 12 \*\*\*\* 4                                                                                                                                                                                                                                                                                                                    |        |

### 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](/docs/develop/guardian/workspace/policies/policy-creation/introduction/events).


# revokeBlock

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. Output of this Block is the documents array.

### Properties

| Block Property                  | Definition                                                                        | Example Input                                                                  | Status |
| ------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------ |
| tag                             | Unique name for the logic block.                                                  | **revokeBlock**                                                                |        |
| permissions                     | Which entity has rights to interact at this part of the workflow.                 | Registrant                                                                     |        |
| defaultActive                   | Shows whether this block is active at this time and whether it needs to be shown. | Checked or unchecked.                                                          |        |
| On errors                       | Called if the system error occurs in the Block                                    | <ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul> |        |
| stop Propagation                | End processing here, don't pass control to the next block.                        | Checked or unchecked.                                                          |        |
| Update previous document status | flag which updates previous document status.                                      | Checked or unchecked.                                                          |        |
| Status value                    | Value of the Previous document status                                             | Waiting for approval                                                           |        |


# setRelationshipsBlock

This block contains DocumentsSourceAddOn and **set relationships** for input document from DocumentsSourceAddOn documents (messageId’s). It doesn’t save document to database.

### Properties

| Block Property   | Definition                                                                        | Example Input                                                                  | Status |
| ---------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------ |
| tag              | Unique name for the logic block.                                                  | **setRelationshipsBlock**                                                      |        |
| permissions      | Which entity has rights to interact at this part of the workflow.                 | VVB                                                                            |        |
| defaultActive    | Shows whether this block is active at this time and whether it needs to be shown. | Checked or unchecked.                                                          |        |
| On errors        | Called if the system error occurs in the Block                                    | <ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul> |        |
| stop Propagation | End processing here, don't pass control to the next block.                        | Checked or unchecked.                                                          |        |
| Include Accounts | Merges all the accounts from the documents                                        | Checked or unchecked.                                                          |        |
| Change Owner     | It takes owner from first document                                                | Checked or unchecked.                                                          |        |
| Include Tokens   | We can get token template name and appropriate token id from related documents    | Checked or unchecked.                                                          |        |


# buttonBlock

### Properties

| Block Property   | Definition                                                                        | Example Input                                                                  | Status |
| ---------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------ |
| tag              | Unique name for the logic block.                                                  | **buttonBlock**                                                                |        |
| permissions      | Which entity has rights to interact at this part of the workflow.                 | VVB                                                                            |        |
| defaultActive    | Shows whether this block is active at this time and whether it needs to be shown. | Checked or unchecked.                                                          |        |
| On errors        | Called if the system error occurs in the Block                                    | <ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul> |        |
| stop Propagation | End processing here, don't pass control to the next block.                        | Checked or unchecked.                                                          |        |

### Button

| Block Property            | Definition                                                                                                                                                                                                           | Example Input                                                                                                            | Status |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------ |
| Type                      | Type of the Button                                                                                                                                                                                                   | <p>Two types of buttons:<br>1. Selector : Simply button. 2. Selector - dialog : button with dialog</p>                   |        |
| Button Tag                | Tag of the button will be chosen in events tab                                                                                                                                                                       | Button\_0                                                                                                                |        |
| Dialog Title              | pop - up dialog title. this field gets enabled when button type is Selector-dialog                                                                                                                                   | Reject                                                                                                                   |        |
| Dialog Description        | It is the text inside dialog pop up. This field is enabled when button type is Selector - dialog                                                                                                                     | Enter reject reason                                                                                                      |        |
| Button Name               | Label of the button                                                                                                                                                                                                  | Validate                                                                                                                 |        |
| Field                     | Field of document to change                                                                                                                                                                                          | option.status                                                                                                            |        |
| Value                     | Value to set                                                                                                                                                                                                         | Validated                                                                                                                |        |
| UI Class                  | UI class of the button                                                                                                                                                                                               | btn-approve                                                                                                              |        |
| hideWhenDiscontinued      | Check if the button should be hidden when policy is discontinued                                                                                                                                                     | Checked/Unchecked                                                                                                        |        |
| Filters                   | array of addition visible filters                                                                                                                                                                                    | <p>Field (field) – field of document.</p><p>Value (value) – field to compare.</p><p>Type (type)– type of comparison.</p> |        |
| dialogResultFieldPath     | This will allow to define destination field where value from dialog will be stored. Also it will not override value of this field, it will only be replaced to array or value will be just pushed to existing array. | Field Path                                                                                                               |        |
| Enable Individual Filters | As per button visibility filters instead of hiding all buttons                                                                                                                                                       | Checked or Unchecked                                                                                                     |        |

### 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": "fa4c1642-700a-44f6-a8eb-1089e77c4d64",
  "blockType": "buttonBlock",
  "type": "selector",
  "uiMetaData": {
    "options": [
      {
        "title": "",
        "name": "Add",
        "tooltip": "",
        "type": "text",
        "value": "Waiting for Validation",
        "uiClass": "btn-approve",
        "bindBlock": "save_added",
        "tag": "Option_0"
      }
    ],
    "content": "VVB",
    "buttons": [
      {
        "tag": "Option_0",
        "name": "Add",
        "type": "selector",
        "filters": [],
        "field": "option.status",
        "value": "Waiting for Validation",
        "uiClass": "btn-approve"
      }
    ]
  }
}

```

{% 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> | Object | VC Document |


# documentValidatorBlock

This block is to validate documents, including linked documents. This block returns an error if at least one of the checks don’t pass. It can be placed as a ‘child’ document, or as a link in the sequence of the blocks.

![](/files/e8fxnpLALHJn8XwWKeIt)

### Properties

<table><thead><tr><th width="208">Block Property</th><th>Definition</th><th>Example Input</th><th>Status</th></tr></thead><tbody><tr><td>tag</td><td>Unique name for the logic block.</td><td><strong>documentValidatorBlock</strong></td><td></td></tr><tr><td>permissions</td><td>Which entity has rights to interact at this part of the workflow.</td><td>VVB</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>On errors</td><td>Called if the system error occurs in the Block</td><td><ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul></td><td></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>DocumentType</td><td>Type of the documents to be validated.</td><td><p>· VC Document</p><p>· VP Document</p><p>· Related VC<br>Document</p><p>. Related VP Document</p></td><td></td></tr><tr><td>Check Schema</td><td>Validates schema documents.</td><td>Schema</td><td></td></tr><tr><td>Check Own Document</td><td>If ‘true’ validates document owners.</td><td>True / False</td><td></td></tr><tr><td>Check Assign Document</td><td>If ‘true’ validates document owners.</td><td>True / False</td><td></td></tr><tr><td>Conditions</td><td>Array containing conditions for validation.</td><td>Array</td><td></td></tr></tbody></table>

![](/files/VGuvDRtWdlGNBxOBgBBS)

### Document Type

The following document types are supported:

1. VC Document : validates the main document and its type (Verifiable Credential).
2. VP Document : validates the main document and its type (Verifiable Presentation).
3. Related VC Document : validates the document linked to the main document and its type (Verifiable Credential)
4. Related VP Document : validates the document linked to the main document and its type (Verifiable Presentation)

### Conditions

#### Condition N

#### Type:

1. Equal – resolves to ‘true’ if value of the field is equal the content of the Value parameter.
2. Not Equal – resolves to ‘true’ if value of the field is NOT equal the content of the Value parameter.
3. In – resolves to ‘true’ if value of the field is present in the array.
4. Not In – resolves to ‘true’ if value of the field is present in the array.

#### Field :

This field of the document to validate the Value parameter.

#### Value:

The content of this parameter is compared to the content of the Field.


# Document Validator Block Source Validations

The Source Validations feature of `documentValidatorBlock` lets a policy step verify that a related document already exists in the Guardian database and that specific fields on that document satisfy conditions defined against the incoming document — before the workflow is allowed to proceed.

### The Problem It Solves

Many environmental MRV workflows depend on sequencing: a monitoring report is only valid after a project registration has been approved; an emission reduction claim must reference a methodology document that is already on record or search by projectID specific document and validate dates. Without a cross-document check at the block level, enforcing this ordering requires either a custom logic block or a manual review gate — all of which add complexity and introduce surface area for errors.

The Source Validations feature moves this responsibility into `documentValidatorBlock` itself. The block can query the Guardian database for documents that match a schema and ownership criteria, then test field-level conditions that span both the incoming document and the queried results, routing the event to the error output if the check fails.

### How It Works

A `documentValidatorBlock` can hold any number of Source Validation entries. Each entry is evaluated independently in order.

**Query phase.** The block builds a database filter from the entry's configuration:

* **Source Collection** — whether to query `VcDocument` or `VpDocument` records.
* **Schema** — restricts the query to documents that match a specific schema.
* **Ownership and assignment flags** — optionally limits results to documents owned by the current user, owned by their group, assigned to the user, or assigned to their group.
* **Source Filters** — field-level conditions on the source documents themselves (e.g. `credentialSubject.0.status` equals `Approved`). Each filter compares a source-document field to either a literal value or a field from the incoming document.

**Condition phase.** Once the query returns a set of candidate source documents, each one is tested against the entry's cross-document **Conditions**. A condition has two sides: each side can be a literal value, a path on the incoming document (`Input Document`), or a path on the candidate source document (`Source Document`). Supported operators are: `equal`, `not_equal`, `in`, `not_in`, `gt`, `gte`, `lt`, `lte`.

**Pass/fail semantics.** The entry passes if **at least one** candidate source document satisfies **all** conditions. If the query returns no documents, or every candidate fails at least one condition, the entry fails.

**Error reporting.** On failure the block constructs a detailed message describing which conditions failed and on how many source documents. If a custom Fail Message is set on the entry, it is prepended to the detail. The error is emitted as a `BlockActionError` that routes the event to the `ErrorEvent` output.

The full validation sequence for a document is:

1. Document existence check
2. Document type check (VC Document, VP Document, Related VC Document, Related VP Document)
3. Ownership checks (user or group)
4. Assignment checks (user or group)
5. Schema validation
6. Same-document Conditions (field conditions on the incoming document only)
7. Source Validations (cross-document, one entry at a time)

Any step that fails stops evaluation immediately and emits the error event.

### Key Distinctions

**Conditions vs. Source Validations.** The block has two separate condition mechanisms. The top-level **Conditions** array checks fields on the incoming document only — no database query is involved. **Source Validations** perform a database query and then compare fields across two documents. Use top-level Conditions for simple field checks; use Source Validations when the check depends on the state of another document.

**Source Filters vs. Source Validation Conditions.** Within a Source Validation entry, **Source Filters** narrow the database query (they affect which documents are candidates). **Conditions** test relationships between the candidate and the incoming document after the query returns. Filters reduce the candidate set; conditions determine whether any candidate in that set is sufficient.

**Pass if any, not pass if all.** The entry passes as soon as one candidate document satisfies all conditions. It does not require every queried document to satisfy the conditions.

### Related

* Task: [Configure Source Validations in documentValidatorBlock](/docs/develop/guardian/workspace/policies/policy-creation/introduction/documentvalidatorblock/configure-source-validations-in-documentvalidatorblock)
* Reference: [documentValidatorBlock](/docs/develop/guardian/workspace/policies/policy-creation/introduction/documentvalidatorblock)


# Configure Source Validations in documentValidatorBlock

Add one or more Source Validation entries to a `documentValidatorBlock` to make a policy step verify that a related document already exists in the Guardian database before allowing the workflow to continue.

### Prerequisites

* You have a policy open in edit mode.
* The policy contains a `documentValidatorBlock`, or you are about to add one.
* You know the schema names of the documents you want to validate against (visible in the Schemas section of the policy configuration).

### Steps

#### Add a Source Validation entry

1. Click the `documentValidatorBlock` in the policy canvas to open its configuration panel.
2. Scroll to the **Source Validations** section and click **Add Source Validation**.
3. In the new entry, open the **Source Collection** dropdown and select **VcDocument** or **VpDocument** depending on the type of documents you are querying.
4. (Optional) Open the **Schema** selector and choose the schema the source documents must match. Leave empty to query all documents in the collection.
5. (Optional) Enable any combination of the four ownership and assignment checkboxes:
   * **Only Own Documents** — restricts results to documents owned by the current user.
   * **Only Own by Group Documents** — restricts results to documents owned by the current user's group.
   * **Only Assigned Documents** — restricts results to documents assigned to the current user.
   * **Only Assigned by Group Documents** — restricts results to documents assigned to the current user's group.
6. (Optional) Enter a **Fail Message**. This text appears at the start of the error message when this entry fails. Use it to explain the business rule being enforced (e.g., `An approved project registration must exist before submitting a monitoring report.`).

#### Add Source Filters

Source Filters narrow which documents the block retrieves from the database. Add a filter for each field on the source document that must match a specific value or a value from the incoming document.

7. Inside the entry, expand **Source Filters** and click **Add Filter**.
8. Set **Field** to the JSON path of the field on the source document (e.g., `status`). Use the document-path picker to browse available fields.
9. Select an **Operator**: `equal`, `not_equal`, `in`, `not_in`, `gt`, `gte`, `lt`, or `lte`.
10. Set **Value Type**:
    * **Value** — compare against a literal string you enter directly.
    * **Variable** — compare against a field from the incoming document; enter the path using the document-path picker (e.g., `credentialSubject.0.projectId`).
11. Enter or select the comparison **Value**.
12. Repeat steps 7–11 for each additional filter.

#### Add cross-document Conditions

Conditions test relationships between fields on the queried source documents and fields on the incoming document. At least one source document must satisfy all conditions for the entry to pass.

13. Inside the entry, expand **Conditions** and click **Add Condition**.
14. Configure the **left side** of the condition:
    * Set **Left Source** to **Input Document**, **Source Document**, or **Value**.
    * If you selected a document source, enter the field path using the document-path picker. If you selected **Value**, enter a literal string.
15. Select an **Operator**.
16. Configure the **right side** of the condition using the same approach as step 14 (**Right Source** and the right-side field or literal).
17. Repeat steps 13–16 for each additional condition.

#### Add more Source Validation entries

18. To enforce multiple independent cross-document checks, click **Add Source Validation** again and repeat steps 3–17 for each entry. All entries must pass for the block to succeed.

#### Save

19. Click **Save** in the configuration panel.

### Result

When the policy executes this block, it processes each Source Validation entry in order. For each entry the block queries the database using the schema, ownership flags, and Source Filters you configured. It then tests each returned document against the Conditions. If at least one source document satisfies all conditions, the entry passes and execution continues to the next entry. If no source document satisfies all conditions — or the query returns no results — the block emits a `BlockActionError` with a detailed message listing which conditions failed and on how many candidate documents. The event is routed to the `ErrorEvent` output.

### Troubleshooting

**"No source documents found" error on every submission.** The query returned zero results. Check that the selected schema matches documents that actually exist in the policy's context, that the ownership/assignment flags match how those documents were created, and that each Source Filter field path is correct.

**Conditions fail even though the expected source document exists.** The error message lists the field name, operator, and values for each failing condition. Confirm that the field paths on both sides resolve correctly — use the document-path picker rather than typing paths manually. Also confirm that the value types are set to **Variable** (not **Value**) when you intend to compare against a field on the incoming document.

**An entry passes when it should fail.** Remember that the pass condition is "at least one source document satisfies all conditions." If multiple source documents match the query and one of them happens to satisfy the conditions, the entry will pass. Add more restrictive Source Filters to narrow the candidate set (e.g., filter documents by `projectId`).

### Related

* Concept: [Document Validator Block Source Validations](/docs/develop/guardian/workspace/policies/policy-creation/introduction/documentvalidatorblock/document-validator-block-source-validations)
* Reference: [documentValidatorBlock](/docs/develop/guardian/workspace/policies/policy-creation/introduction/documentvalidatorblock)


# tokenActionBlock

This block is responsible in performing automatic actions on the token.

### Properties

<table><thead><tr><th width="208">Block Property</th><th>Definition</th><th>Example Input</th><th>Status</th></tr></thead><tbody><tr><td>tag</td><td>Unique name for the logic block.</td><td><strong>tokenActionBlock</strong></td><td></td></tr><tr><td>permissions</td><td>Which entity has rights to interact at this part of the workflow.</td><td>VVB</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>On errors</td><td>Called if the system error occurs in the Block</td><td><ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul></td><td></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>Token</td><td>The token which is affected by the action</td><td>iREC token</td><td></td></tr><tr><td>Account Type</td><td><p>The type of the account under which the action is performed. If set to ‘Default’ the account of the currently logged in user is used (i.e. the owner of the document).</p><p>If set to ‘Custom’ the account specified in the ‘accountId’ field is used.</p></td><td>Custom</td><td></td></tr><tr><td>Account Id (Field)</td><td>The value from this field is used as the ID of the account under which the action is performed when ‘Account Type’ is set to ‘Custom’.</td><td>field0</td><td></td></tr><tr><td>Action</td><td>Action to be performed on Token</td><td><ul><li>Associate</li><li>Dissociate</li><li>Freeze</li><li>Unfreeze</li><li>Grant Kyc</li><li>Revoke Kyc</li></ul></td><td></td></tr><tr><td>Use Template</td><td>This needs to be enabled if we need to use token template, which is created already.</td><td>Enabled or Disabled</td><td></td></tr><tr><td>Token Template</td><td>Which will take created tokenId from input document by template name</td><td>token_template<em>_</em>0</td><td></td></tr></tbody></table>

![](/files/QXzP7UikLo5MP7Mrg47Y)

![](/files/aIPUCgKibXy111Hhxhb8)

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

1. Only fields of ‘Hedera Account’ type can be used for ‘accountId’.
2. If the field specified in the ‘accountId’ is not found in the current document then the system will look for it in the parent documents.
3. ‘Associate’ and ‘Dissociate’ actions are not available when ‘Account Type’ is set to ‘Custom’. For these operations ‘[**tokenConfirmationBlock**](/docs/develop/guardian/workspace/policies/policy-creation/introduction/tokenconfirmationblock)’ should be used instead.
   {% endhint %}

### Actions

| Action Name | Purpose                                                                                                                                                        |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Associate   | Links the account with the token. This operation is required to enable the account to perform transactions (including receiving) with the token.               |
| Dissociate  | Removes the aforementioned ‘link’.                                                                                                                             |
| Freeze      | Freezes the account                                                                                                                                            |
| Unfreeze    | Unfreezes the account                                                                                                                                          |
| Grant KYC   | This action is mandatory if the token is configured to require KYC. The owner of the token is required to ‘grant KYC’ to enable transactions with the account. |
| Revoke KYC  | This revokes the account’s permission to participate in transactions with the token.                                                                           |

![](/files/WXU21LRZYqw00EBNcuxt)


# tokenConfirmationBlock

This block enables the owner of the private key for the account to manually perform operations with the token, including those not available in the ‘[**tokenActionBlock**](/docs/develop/guardian/workspace/policies/policy-creation/introduction/tokenactionblock)**’.**

### **1. Properties**

| Block Property     | Definition                                                                                                                                                                                                                                                     | Example Input                                                                  | Status |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------ |
| tag                | Unique name for the logic block.                                                                                                                                                                                                                               | **tokenConfirmationBlock**                                                     |        |
| permissions        | Which entity has rights to interact at this part of the workflow.                                                                                                                                                                                              | VVB                                                                            |        |
| defaultActive      | Shows whether this block is active at this time and whether it needs to be shown.                                                                                                                                                                              | Checked or unchecked.                                                          |        |
| On errors          | Called if the system error occurs in the Block                                                                                                                                                                                                                 | <ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul> |        |
| Stop Propagation   | End processing here, don't pass control to the next block.                                                                                                                                                                                                     | Checked or unchecked.                                                          |        |
| Token              | The token which is affected by the action                                                                                                                                                                                                                      | iREC token                                                                     |        |
| Account Type       | <p>The type of the account under which the action is performed. If set to ‘Default’ the account of the currently logged in user is used (i.e. the owner of the document).</p><p>If set to ‘Custom’ the account specified in the ‘accountId’ field is used.</p> | Custom                                                                         |        |
| Account Id (Field) | The value from this field is used as the ID of the account under which the action is performed when ‘Account Type’ is set to ‘Custom’.                                                                                                                         | field0                                                                         |        |
| Action             | Action to be performed on Token                                                                                                                                                                                                                                | <ul><li>Associate</li><li>Dissociate</li></ul>                                 |        |
| Use Template       | This needs to be enabled if we need to use token template, which is created already.                                                                                                                                                                           | Enabled/Disabled                                                               |        |
| Token Template     | Which will take created tokenId from input document by template name                                                                                                                                                                                           | token\_template\_\_\_0                                                         |        |

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

1. Only fields of ‘Hedera Account’ type can be used for ‘accountId’.
2. If the field specified in the ‘accountId’ is not found in the current document then the system will look for it in the parent documents.
3. Users can skip the action by selecting “I will *Action* manually” option in the UI. This would require the user to perform the corresponding action off-Guardian platform (directly on Hedera chain).
   {% endhint %}

![Block Properties](/files/s5mlBay11jl6ADKmMi41)

![JSON View of the Block](/files/uP1RFSkYD1PcBh7O0TOx)

![Configuring tokenConfirmationBlock](/files/KKnu3FU1TwJBAjatlGtU)

![Creating Event to move to next step](/files/xZg8psih7toBJGar4Hu5)

### 2. Performing Token Associate using Guardian UI

The user need to input the private key for the account to enable Guardian to perform the action. The key is used once for the operation specified, it is not saved and not logged anywhere.

{% hint style="info" %}
**Note:** Users can skip the action in UI if they prefer to perform it outside Guardian (directly with Hedera blockchain).
{% endhint %}

![](/files/cX3HR7w8NV4owky93eNe)

### 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" %}

```
{
  "id": "484c57c2-5ceb-41ed-97b3-61c52fce473e",
  "blockType": "tokenConfirmationBlock",
  "action": "associate",
  "accountId": "0.0.1",
  "tokenName": "GHG Token",
  "tokenSymbol": "GHG",
  "tokenId": "0.0.3121118"
}

```

{% 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                |
| -------------------------------------------------- | ------ | -------------------------- |
| action<mark style="color:red;">\*</mark>           | String | action                     |
| hederaAccountKey<mark style="color:red;">\*</mark> | String | Hedera Account Private Key |


# mintDocumentBlock

This block is responsible for adding configurations on calculating the amount of tokens to be minted.

### Properties

<table><thead><tr><th width="208">Block Property</th><th>Definition</th><th>Example Input</th><th>Status</th></tr></thead><tbody><tr><td>tag</td><td>Unique name for the logic block.</td><td><strong>mintDocumentBlock</strong></td><td></td></tr><tr><td>permissions</td><td>Which entity has rights to interact at this part of the workflow.</td><td>VVB</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>On errors</td><td>Called if the system error occurs in the Block</td><td><ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul></td><td></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>

### Additional Properties

<table><thead><tr><th width="208">Block Property</th><th>Definition</th><th>Example Input</th><th>Status</th></tr></thead><tbody><tr><td>Round Method</td><td>The method used to round the number of tokens.</td><td><p>Select an option from the dropdown ('Round to nearest' is selected by default):</p><ul><li>Round up</li><li>Round down</li><li>Round to nearest</li></ul></td><td></td></tr><tr><td></td><td></td><td></td><td></td></tr></tbody></table>

### UI Properties

| UI Property        | Definition                                                                                                                                                          | Example Input                                                                     |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| Token              | The token which is affected by the action                                                                                                                           | GHG Token                                                                         |
| Account Type       | The value from this field is used as the ID of the account under which the action is performed when ‘Account Type’ is set to ‘Custom Account Field’.                | <ul><li>Custom Account Field</li><li>Custom Account Value</li></ul>               |
| Rule               | Math expression for calculation of the amount of tokens to mint.                                                                                                    | field7 \* 100                                                                     |
| Account Id (Field) | The value from this field is used as the ID of the account which is used for token transfer action when ‘Account Type’ is set to ‘Custom’.                          | field5                                                                            |
| Account Id (Value) | Allow users to set custom Hedera account id directly in policy configuration (for token transferring). This field is displayed only when Custom Account Value type. | 0.0.48640912                                                                      |
| Memo               | The value in this field is used to customize the Memo field name.                                                                                                   | "mint date is $ {document.verifiableCredential\[0],credentialSubject\[0].field5}" |
| Use Template       | This needs to be enabled if we need to use token template, which is created already.                                                                                | Enabled/Disabled                                                                  |
| Token Template     | Which will take created tokenId from input document by template name                                                                                                | token\_template\_\_\_0                                                            |

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

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

1. Only fields of ‘Hedera Account’ type can be used for ‘accountId’.
2. If the field specified in the ‘accountId’ not found in the current document the system will look for it in the parent documents.
   {% endhint %}


# Events

There is a new tab called ‘Events’ for every block in the GUI where events can be configured. The events allow Policy creators to transfer control/execution on exit from the current block to an arbitrary block and thus build non-linear workflows.

![](/files/SMtelQlqCmQatiLJDu9V)

### Settings:

| 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.                                                                                |

![](/files/SMtelQlqCmQatiLJDu9V)

![](/files/FqSLl5xOMqjuW0pVTAGm)

{% hint style="info" %}
Note: The event is shown in both source and target blocks tabs regardless of where it was added initially.
{% endhint %}

### Default Events

Default events correspond to the implicit default transfer of execution control from the current to the next (adjacent) block graphically represented by the block immediately below the current one.

Default events can be switched off by setting ‘Disabled’ to ‘true’ on the Events tab, or ‘Stop Propagation’ to ‘true’ on the Properties tab as in the older Guardian versions.

![](/files/UQ7sZBguzDaD0ghLC4sS)

### Output Events

Output events are events which are created by the ‘Source’ blocks.

**Output Event (enum):**

**All Blocks:**

* RunEvent - appears upon the completion of main logic of the block.
* RefreshEvent - triggered upon the changes in the state of the block.

![](/files/uWI3JlMub47QF9hSrTx3)

**TimerBlock:**

* TimerEvent – triggered upon each ‘tick’ of the timer

**switchBlock:**

* Condition 1..N - each condition expression in the switch block maps to the corresponding event created upon the evaluation of its condition into ‘true’

![](/files/huuq8zrGHki593hnoRxH)

**InterfaceActionBlock:**

* Option 1..N - each Option (button) triggers a corresponding event upon the button press action from the user

![](/files/8Col1pFQWF31XV2SsINo)

#### Calculate Block, Custom Logic Block, DocumentValidatorBlock, ExternalDataBlock, MintBlock, Reassigning Block, RequestVcDocumentBlock, RetirementBlock, RevokeBlock, SendToGuardianBlock, TokenActionBlock, TokenConfirmationBlock

* Error Event : Which is called and passed the input data when error occur.

### Input Events

Input Events are received and processed by the egress interface of the ‘Target’ block.

**Input Event (enum):**

**All Blocks:**

* RunEvent - triggers the execution of the main logic of the block.
* RefreshEvent - triggers the refresh of the block (in the UI it re-draws the component)

**aggregateDocumentBlock:**

* TimerEvent - triggers the execution of the time(period)-activated aggregation logic, and passes the aggregated data further
* PopEvent - removes the document from the aggregation.

![](/files/CNrYv4tZtrwdrBKZiyNT)

**timerBlock:**

* StartTimerEvent - starts the timer for the user (to ‘tick’ for the time-activated aggregation logic)
* StopTimerEvent – stops the ‘ticking’ timer for the user

#### RequestVcDocumentBlock:

* RestoreEvent - Which receive input vc document to restore data.

#### mintDocumentBlock:

* AdditionalMintEvent - allows linking of the result of one mint block with another mint block.
* RetryMintEvent - It allows to retry mint action if there were some errors, issues there. Environment variable RETRY\_MINT\_INTERVAL is setting up retry mint interval (in minutes), default is 10 minutes.

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

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

1. The link starts with “RunEvent” of the main Mint Block and ends with “AdditionalMintEvent” of the secondary Mint Block
2. “Default Event” of the main Mint Block must be switched off if linked Mint Blocks follow each other
   {% endhint %}

### Event Actor

Allows to change the user-context of the execution

*For example*: in the situation where the Standard Registry confirms the form data from the user and the Policy author would like to come back to the execution of the StepBlock as the original user the ‘Document Owner’ should be configured here instead of the ‘Event Initiator’.

* Event Initiator - Actor which triggered the event.
* Document Owner- Actor is changed to the owner of the document.
* Document Issuer - Actor is changed to the user who signed (confirmed) the document.

### Viewer

#### Output events

![](/files/HQDyzC3BuQwqjk8iML0b)

#### Input events

![](/files/AzY2ccvZRbSLs1jF9G2F)

#### Default Events

![](/files/3953ympYWMQKQzTtO99s)

#### Tooltips

![](/files/Gm9ypZK0Ul4AyVUfNt8V)

#### Filters

![](/files/b6Z6m1EoZMRdAdKtqBDh)


# groupManagerBlock

This block allows to manage group membership, add and remove users from the group.

### 1. Properties

| Block Property   | Definition                                                                        | Example Input                                                                               | Status |
| ---------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------ |
| tag              | Unique name for the logic block.                                                  | **groupManagerBlock**                                                                       |        |
| permissions      | Which entity has rights to interact at this part of the workflow.                 | NoRole                                                                                      |        |
| defaultActive    | Shows whether this block is active at this time and whether it needs to be shown. | Checked or unchecked.                                                                       |        |
| On errors        | Called if the system error occurs in the Block                                    | <ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul>              |        |
| Stop Propagation | End processing here, don't pass control to the next block.                        | Checked or unchecked.                                                                       |        |
| Can Invite       | specifies who can create invites                                                  | <p>· Group Owner – only the creator of the group</p><p>· All – all members of the group</p> |        |
| Can Delete       | specifies who can remove users from the group                                     | <p>· Group Owner – only the creator of the group</p><p>. All – all members of the group</p> |        |

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

### 2. Usage

#### 2.1 **List of the groups in which the user is included:**

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

#### **2.2 List of the users included in the group**

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

#### **2.3 Inviting users to groups**

First step is to select the role to invite the user as shown below:

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

Next step is to copy and send the unique invite or the link to the invite.

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

#### 2.4 **Removing users from groups**

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

### 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
{
  "data": [
    {
      "id": "6b3efd88-037c-4335-a4d1-02776e23973c",
      "role": "VVB(manager)",
      "groupName": "VVBs",
      "groupLabel": "vvb_group1",
      "type": "Owner",
      "groupRelationshipType": "Multiple",
      "groupAccessType": "Private",
      "canInvite": true,
      "canDelete": true,
      "roles": [
        "VVB"
      ],
      "data": [
        {
          "did": "did:hedera:testnet:HdSCbrXJjjfvzymnnzzybNVWQGGGY48p6JGo6Ao5UHnT_0.0.3075949",
          "username": "Virtual User 1",
          "role": "VVB(manager)",
          "type": "Owner",
          "current": true
        },
        {
          "did": "did:hedera:testnet:CJotqpGfK9zVqDHgjtkHg5EPvkTShQVc3hZjojw8St3N_0.0.3075949",
          "username": "Virtual User 2",
          "role": "VVB",
          "type": "Member",
          "current": false
        }
      ]
    }
  ]
}


```

{% 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      |
| ----------------------------------------- | ------ | ---------------- |
| action<mark style="color:red;">\*</mark>  | String | invite/delete    |
| role<mark style="color:red;">\*</mark>    | String | role             |
| group<mark style="color:red;">\*</mark>   | String | group            |
| user<mark style="color:red;">\*</mark>    | String | User DID         |
| message<mark style="color:red;">\*</mark> | String | removing message |


# multiSignBlock

This block provides a way to specify multiple signators for a single VC document, and then create a VP based on it.

### 1. Properties

| Block Property   | Definition                                                                                                                                                     | Example Input                                                                  | Status |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------ |
| tag              | Unique name for the logic block.                                                                                                                               | **multiSignBlock**                                                             |        |
| permissions      | Which entity has rights to interact at this part of the workflow.                                                                                              | NoRole                                                                         |        |
| defaultActive    | Shows whether this block is active at this time and whether it needs to be shown.                                                                              | Checked or unchecked.                                                          |        |
| On errors        | Called if the system error occurs in the Block                                                                                                                 | <ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul> |        |
| Stop Propagation | End processing here, don't pass control to the next block.                                                                                                     | Checked or unchecked.                                                          |        |
| Threshold (%)    | Proportion Of signators which are required to sign the document to achieve quorum for it to transition to ‘signed’ status. Must be a number between 0 and 100. | 0-100                                                                          |        |

{% hint style="info" %}
**Note:** The system assigns ‘not signed’ status to the document when 100 – threshold percentage of users indicated rejection status.
{% endhint %}

### 2. Events

| Event                         | Description                                                                          | Content                                                                     |
| ----------------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- |
| SignatureQuorumReachedEvent   | This event occurs when the threshold number (quorum) of signatures has been reached. | now-signed target VC document which can then be used for further processing |
| SignatureSetInsufficientEvent | This event occurs when the threshold number (quorum) of rejections has been achieved | rejected (target) VC document which can be used for further processing      |

### 3. Data Format

#### 3.1 POST request

```
{
	"document":{
		"id":"…" – ID of the VC document
	},
	"status":"SIGNED" – new status, can be SIGNED or DECLINED
}

```

#### 3.2 GET request

```
{
	blockType: "multiSignBlock"
	id:"61ed0335-8b7e-44d9-aedd-0c86c5806442"
	status: {
		confirmationStatus: - final status, it is ‘null’ if the quorum is not reached
		data: [
				{
						username,
						did – did and username of the user which took the decision
						status – the decision of the user, the value space is: SIGNED/DECLINED
		                 }
		       ] 
	         }
}

```

#### Array of the decisions for each user can be as follows:

| Type of Decision  | Description                                                                                                |
| ----------------- | ---------------------------------------------------------------------------------------------------------- |
| declinedCount     | number of users who declined signing the document                                                          |
| declinedPercent   | percentage of users who need to decline signing the document                                               |
| declinedThreshold | threshold number of users who need to decline signing the document to reach the final decision             |
| documentStatus    | status of the document for the current users, null if the user has not made a selection to sign or decline |
| signedCount       | number of users who have signed the document                                                               |
| signedPercent     | percentage of users who have signed the document                                                           |
| signedThreshold   | threshold number of users who need to sign the document to reach the final decision                        |
| threshold         | threshold in terms of percentage                                                                           |
| total             | total number of users in the signing group                                                                 |

### 4. Example

#### 4.1 Important Points

4.1.1 multiSignBlock must be used with Groups.

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

4.1.2 multiSignBlock must be child block of grid block to receive all data it requires to operate.

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

### 5. UI

#### 5.1 Signing the document

We have an option of Signing/ Declining the document by clicking on "Sign" or "Decline" button for the document as shown below:

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

#### 5.2 Threshold Display

Number of users, who have signed or declined the document can be displayed with threshold as shown below:

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

#### 5.3 Detailed Signature Information

To get detailed information on Signature status, we have an info icon near the threshold as shown below:

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

#### 5.4 Final Signature Result

To get the final Signature Result with detailed information such as which users have Signed / Declined, we need to hover on the Status as shown below:

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

### 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": "1c922d1a-7f9d-492f-b0f9-f319eb2b66be",
  "blockType": "multiSignBlock"
}

```

{% 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     |
| ------------------------------------------ | ------ | --------------- |
| status<mark style="color:red;">\*</mark>   | String | Signed/Declined |
| document<mark style="color:red;">\*</mark> | Object | VC Document     |


# customLogicBlock

## Properties

<table><thead><tr><th width="208">Block Property</th><th>Definition</th><th width="200">Example Input</th><th>Status</th></tr></thead><tbody><tr><td>tag</td><td>Unique name for the logic block.</td><td><strong>customLogicBlock</strong></td><td></td></tr><tr><td>permissions</td><td>Which entity has rights to interact at this part of the workflow.</td><td>NoRole</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>On errors</td><td>Called if the system error occurs in the Block</td><td><ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul></td><td></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>Output Schema</td><td>Sending the logic output to this particular Schema</td><td>Report Employee schema</td><td></td></tr><tr><td>Document Signer</td><td>defines who will sign processed document.<br>Options:<br>1. Policy Owner<br>2. First Document Owner<br>3. First Document Issues</td><td>Policy Owner</td><td></td></tr><tr><td>Id Type</td><td>defines Id Type in credential subject of processed document.<br>Options:<br>1. DID (new DID)<br>2. UUID (new UUID)<br>3. Owner (Owner DID)</td><td>UUID (new UUID)</td><td></td></tr></tbody></table>

{% hint style="info" %}
**Note:** Only this block supports artifacts for now.
{% endhint %}

This block supports two types of artifacts : JSON (.json) and Executable Code (.js).

**JSON** : will be added to the “artifacts” variable which is array in specific order (for example artifacts\[0] is e\_grid\_mapping json object).

**Executable Code** : will be executed before main function.

To access table data in custom logic block, please check [Custom Logic Block & Tables](/docs/develop/guardian/workspace/schemas/available-schema-types/table-data-input-field/custom-logic-block-and-tables) for more details.


# splitBlock

This block allows to accumulate VC documents and produce new VCs in fixed chunks.

If the value in the VC is higher than the chunking threshold the VC would be spilt into multiple VCs containing values equal to the threshold value.

## 1. Properties

<table><thead><tr><th width="208">Block Property</th><th>Definition</th><th width="200">Example Input</th><th>Status</th></tr></thead><tbody><tr><td>tag</td><td>Unique name for the logic block.</td><td><strong>splitBlock</strong></td><td></td></tr><tr><td>permissions</td><td>Which entity has rights to interact at this part of the workflow.</td><td>NoRole</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>On errors</td><td>Called if the system error occurs in the Block</td><td><ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul></td><td></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>Threshold</td><td>The size of a single ‘portion’ (chunk) the original document would be split into.<br>Note: It is always number>0</td><td>1000</td><td></td></tr><tr><td>Source field</td><td>It is the path to the field in the VC document which is the parameter used in the calculation of the ‘size’ of the VC.<br><strong>Note</strong>: <em>is a field to which the ‘source field’ path points. It must be of numeric type.</em></td><td>source path link</td><td></td></tr></tbody></table>

## 2. Data(VC documents) format

After ‘splitting’ of the VC document into several chunks these new created VCs will contain:

1. All fields except the ‘source field’ copied without any changes.
2. Added **evidence** section of the following content:

```
{
            "type": [
                "SourceDocument"
            ],
            "messageId": "1655895001.624621306",
            "sourceField": "document.credentialSubject.0.field0",
            "sourceValue": 200,
            "threshold": 50,
            "chunkNumber": 1,
            "maxChunk": 4
        }

```


# Create Token Block

## Properties

| Block Property   | Definition                                                                                      | Example Input                              | Status |
| ---------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------ | ------ |
| type             | A type of the block which creates a form from the schema, and sends the document to the server. | **Create Token Block** (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.                      |        |
| stop propagation | End processing here, don't pass control to the next block.                                      | Checked or Unchecked.                      |        |
| Token Template   | We can set template by which we want to create token                                            | token\_template\_\_\_0                     |        |

## 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.                                                                                                                              |
| 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."                                                                        |

### 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": "a411e417-bff7-49dc-bbf0-a4e5b7501b73",
  "blockType": "createTokenBlock",
  "uiMetaData": {
    "type": "page",
    "title": "Create Token",
    "description": "Please enter token info"
  },
  "active": true,
  "data": {
    "templateTokenTag": "token_template_0",
    "tokenType": "fungible",
    "decimals": 3,
    "enableAdmin": true,
    "changeSupply": true
  }
}
```

{% 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              |
| ---------------------------------------------- | ------- | ------------------------ |
| tokenName<mark style="color:red;">\*</mark>    | String  | Token Name               |
| tokenSymbol<mark style="color:red;">\*</mark>  | String  | Token Symbol             |
| tokenType<mark style="color:red;">\*</mark>    | String  | Fungible or Non Fungible |
| decimals<mark style="color:red;">\*</mark>     | String  | Token decimals           |
| enableAdmin<mark style="color:red;">\*</mark>  | Boolean | Enable Admin Flag        |
| enableSupply<mark style="color:red;">\*</mark> | Boolean | Enable Supply Flag       |
| enableFreeze<mark style="color:red;">\*</mark> | Boolean | Enable Freeze Flag       |
| enableKYC<mark style="color:red;">\*</mark>    | Boolean | Enable KYC Flag          |
| enableWipe<mark style="color:red;">\*</mark>   | Boolean | Enable Wipe Flag         |


# impactAddon

This Addon for the mint block which allows to add additional info for the token being created.

### 1. Properties

<table><thead><tr><th width="200.33333333333331">Property Name</th><th>Description</th><th>Example</th><th>Status</th></tr></thead><tbody><tr><td>Tag</td><td>Unique name for the logic block.</td><td><strong>impactAddon_1</strong></td><td></td></tr><tr><td>Permissions</td><td>Which entity has rights to interact at this part of the workflow.</td><td>Standard Registry</td><td></td></tr><tr><td>Default Active</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>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>On Errors</td><td>Called if the system error occurs in the Block</td><td><ul><li>No action</li><li>Retry</li><li>Go to step</li><li>Go to tag</li></ul></td><td></td></tr><tr><td>Impact Type</td><td>shows the type of the impact</td><td>Primary Impacts / Secondary Impacts</td><td></td></tr><tr><td>Label</td><td>Title of the Impact</td><td>Test</td><td></td></tr><tr><td>Description</td><td>Description of the impact</td><td>Impact description</td><td></td></tr><tr><td>Amount (Formula)</td><td>Formula for calculating the impact quantitative representation based on the data from the source VC</td><td>field0</td><td></td></tr><tr><td>Unit</td><td>Unit of measurement of impact amounts</td><td>Kg</td><td></td></tr></tbody></table>

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

### 2. Data Format

Adding impactAddon changes VP documents such that:

2.1 New VC documents are added for each impact describing it

```
{
    "id": "732d46ca-1e19-43a2-a4b1-49cf5ea08aa9",
    "type": [
        "VerifiableCredential"
    ],
    "issuer": "did:hedera:testnet:BJDCUTd8gFSaFwW4w7Tw8dbx7DfnkfLjJ14s2dquesS9_0.0.49039174",
    "issuanceDate": "2022-12-06T11:27:37.964Z",
    "@context": [
        "https://www.w3.org/2018/credentials/v1"
    ],
    "credentialSubject": [
        {
            "@context": [
                "ipfs://bafkreiabgmqbzd4s2u2jy74ebkawbtvs3ohc76qhphx4vvuymskpfmjj2u"
            ],
            "type": "ActivityImpact",
            "impactType": "Primary Impacts",
            "date": "2022-12-06T11:27:37.959Z",
            "amount": "2000",
            "unit": "kg",
            "label": "Test 1",
            "description": "Test Description 1"
        }
    ],
    "proof": {
        "type": "Ed25519Signature2018",
        "created": "2022-12-06T11:27:37Z",
        "verificationMethod": "did:hedera:testnet:BJDCUTd8gFSaFwW4w7Tw8dbx7DfnkfLjJ14s2dquesS9_0.0.49039174#did-root-key",
        "proofPurpose": "assertionMethod",
        "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..nK_fvwC9nW9jtKHm2U4yAHhIcgpGCkr1H7PiPNwKzAj9gW2sblpu0TAQEow9OR9v1aREEH-fFLmyAGEfXWfXAw"
    }
}

```

2.2 All source VCs are substituted for a single cumulative VC containing links to the source (original) VCs.

```
{
    "id": "443e9e7b-3a67-4ad9-a22d-d85c2d28562f",
    "type": [
        "VerifiableCredential"
    ],
    "issuer": "did:hedera:testnet:BJDCUTd8gFSaFwW4w7Tw8dbx7DfnkfLjJ14s2dquesS9_0.0.49039174",
    "issuanceDate": "2022-12-06T11:27:37.936Z",
    "@context": [
        "https://www.w3.org/2018/credentials/v1"
    ],
    "credentialSubject": [
        {
            "@context": [
                "ipfs://bafkreicnjditzstltfyu2327pqqcstuwl5vegwe2hepbwcque2gjvwsm3y"
            ],
            "type": "TokenDataSource",
            "dataSource": [
                "1670.326057800",
                "1670.451857512"
            ]
        }
    ],
    "proof": {
        "type": "Ed25519Signature2018",
        "created": "2022-12-06T11:27:37Z",
        "verificationMethod": "did:hedera:testnet:BJDCUTd8gFSaFwW4w7Tw8dbx7DfnkfLjJ14s2dquesS9_0.0.49039174#did-root-key",
        "proofPurpose": "assertionMethod",
        "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..N5sOQOgxBxPdvGvCJbfJ4rWBc6374Ht96xKTAN6Pwrhr8Pk4SWqS6IwDePBySTIbvVETPFFxjzGQZMsbENx5BA"
    }
}

```


# Http Request Block

Block for retrieving information from outside (3rd party) services via HTTP requests.

## Properties

| Property Name    | Description                                                                       | Example                   | Status |
| ---------------- | --------------------------------------------------------------------------------- | ------------------------- | ------ |
| Tag              | Unique name for the logic block.                                                  | **Http\_Block**           |        |
| Permissions      | Which entity has rights to interact at this part of the workflow.                 | Standard Registry         |        |
| Default Active   | 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      |        |
| On Errors        | Called if the system error occurs in the Block                                    | <p>No action<br>Retry</p> |        |
| URL              | URL of the external service end point                                             | <http://localhost:8080>   |        |
| Method           | HTTP method of the request                                                        | GET/POST/DELETE/PUT/PATCH |        |
| Body             | Body of the HTTP request                                                          | $(document)               |        |
| Headers          | Additional HTTP headers (can be used for authentication purposes)                 | Bearer $(document).Source |        |

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

To prevent sensitive headers such as Bearer tokens from being published to IPFS during policy export, an "Include value in exported policy" checkbox was added to each HTTP header in the httpRequestBlock.

This mechanism ensures that secrets are not accidentally leaked when the policy is published and stored on IPFS.

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

1. By default, this checkbox is set to false, meaning the header's value will not be included in the exported policy.
2. If a header has a value but the "Include" option is not enabled, publishing the policy will fail with a validation error. The user must either enable the checkbox or remove the header value.
   {% endhint %}

## 2. Dynamic Variables

The values of the URL, Body and Header parameters can contain variables of the format ${variable}.

Possible values are as follows:

* “did” – DID of the current user
* “username” – name of the current user
* “document” or “documents” – a single document or an array of document correspondingly, which have been passed to the block on entry


# historyAddon

This block turn on history on interfaceDocumentsSourceBlock. This block should be placed inside interfaceDocumentsSourceBlock.

### Properties

| Property Name           | Description                                                                       | Example                                                   | Status |
| ----------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------- | ------ |
| Tag                     | Unique name for the logic block.                                                  | **history\_addon**                                        |        |
| Permissions             | Which entity has rights to interact at this part of the workflow.                 | Registrant                                                |        |
| Default Active          | 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                                      |        |
| On Errors               | Called if the system error occurs in the Block                                    | <p>- No action<br>- Retry</p>                             |        |
| timelineLabelPath       | Label of timeline point                                                           | “option.status”. It is default value if setting is empty  |        |
| timelineDescriptionPath | Description of timeline point                                                     | “option.comment”. It is default value if setting is empty |        |

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


# selectiveAttributes Block

This Block can be placed inside documentsSourceAddon. This will filter attributes (option field) in documents returned by documentsSourceAddon.

### Properties

| Property Name    | Description                                                                       | Example                                                                                                                                                                                                       | Status |
| ---------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| Tag              | Unique name for the logic block.                                                  | **selective\_attributes\_addon**                                                                                                                                                                              |        |
| Permissions      | Which entity has rights to interact at this part of the workflow.                 | Registrant                                                                                                                                                                                                    |        |
| Default Active   | 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                                                                                                                                                                                          |        |
| On Errors        | Called if the system error occurs in the Block                                    | <p>- No action<br>- Retry</p>                                                                                                                                                                                 |        |
| Attributes       | Array of attributes to select                                                     | <p>"attributes": \[</p><p>{</p><p>"attributePath": "status"</p><p>},<br><br><strong>Note:</strong> If value is empty no attributes will be selected and field option in returned documents will be empty.</p> |        |

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


# tagsManagerBlock

Block ***tagsManager*** is responsible for managing tags in policies. This block should be added as a ‘child’ block to the grid and linked to one of its columns. This block does not have any settings.

## Properties

| Property Name    | Description                                                                       | Example                       | Status |
| ---------------- | --------------------------------------------------------------------------------- | ----------------------------- | ------ |
| Tag              | Unique name for the logic block.                                                  | **tags\_manager**             |        |
| Permissions      | Which entity has rights to interact at this part of the workflow.                 | Registrant                    |        |
| Default Active   | 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          |        |
| On Errors        | Called if the system error occurs in the Block                                    | <p>- No action<br>- Retry</p> |        |

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


# extractDataBlock

This block is used for VC documents which are based on (or ‘conform to’) a schema which contains embedded schemas, extractDataBlock provides means to extract a data set which corresponds to any of these embedded schemas (at any depth level), and if required after processing to return the updated values back into the VC dataset to their original ‘place’.

## 1. Properties

| Property Name | Details                                                                                                                                                                 | Example                                                                                                                                                                                                    | Status |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| Action        | an action which is executed by the block                                                                                                                                | <p>o Get – find and extract the part of the document which corresponds to the specified schema</p><p>o Set – update the part of the document, which corresponds to the specified schema, with new data</p> |        |
| Schema        | the schema which is target of the action. It is used to identify the embedded part of the data object - i.e. the field in the document which corresponds to this schema | Contact Details (1.1)                                                                                                                                                                                      |        |

### 1.1 Extraction

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

### 1.2 Update

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


# externalTopicBlock

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.

<figure><img src="/files/1tz7kEJ2nVqLJbCnkiZZ" alt=""><figcaption></figcaption></figure>

## 1.1 Properties

| Property Name    | Description                                                                                                                                                                                                                                                                                                  | Example                       | Status |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- | ------ |
| Tag              | Unique name for the logic block.                                                                                                                                                                                                                                                                             | **externalTopic**             |        |
| Permissions      | Which entity has rights to interact at this part of the workflow.                                                                                                                                                                                                                                            | Standard Registry             |        |
| Default Active   | 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          |        |
| On Errors        | Called if the system error occurs in the Block                                                                                                                                                                                                                                                               | <p>- No action<br>- Retry</p> |        |
| Schema           | a schema containing the minimal structure/content requirements for the VC documents to comply with in order to be ingested from the topic. A compliant document can be a super set of the minimal schema, i.e. it can contain other properties/data so long as it also has what is specified in this schema. | Schema                        |        |

## 1.2 Data Format

### 1.2.1 GET

```
{
    documentTopicId – topic which contains links to documents to be ingested (optional/required depending on the stage in the workflow)
    policyTopicId – topic which contains policy messages (optional/required depending on the stage in the workflow)
    instanceTopicId – topic which contains policy instance specific messages (optional/required depending on the stage in the workflow)
    documentMessage – message with the information about the document topic(documentTopicId)
    policyMessage – message with the information about the policy topic(policyTopicId)
    policyInstanceMessage – message with the information about the policy instance topic(instanceTopicId)
    schemas – schemas accessible in the select policy (if specified)
    schema – schema which was selected by the user
    lastUpdate – time stamp of the last synchronisation
    status – link status
}

```

### 1.2.2 POST

* **Topic selection** – allow the user to specify the topic which contains messages about the documents to be ingested.

```
{
    "operation": "SetTopic",
    "value": "topicId"
}
```

* **Schema selection** – allows the user to specify the schema for selecting (filtering) the documents to be ingested.

```
{
    "operation": "SetSchema",
    "value": "schemaId"
}
```

* **Schema verification** – verifies if the selected schema is compliant with the settings of the block

```
{
    "operation": "VerificationSchema",
    "value": "schemaId"
}
```

* **Manual loading of the documents** – triggers immediate (out of schedule) synchronization of the documents (the automatic synchronization will still takes place as per the schedule)

```
{
    "operation": "VerificationSchemas",
}
```

* **Reset of the link** – allows to reset settings and specify afresh.

```
{
    "operation": "Restart",
}
```


# messagesReportBlock

## 1. messagesReportBlock:

This Block allows to create report based on the inter-referenced messages.

![image1.png](/files/QIZXi1f6VcL2U38quLNL)

## **1.1 Properties**

Does not contain additional settings.

## **1.2 Data format**

### **GET**

**status** – current report status

1. FAILED – error encountered during the building
2. STARTED – reporting building is in progress
3. FINISHED – reporting building has been successfully completed

**target** – the document which is the subject of the report

**report** – the current report

```
{
"roles" – documents showing users and their roles
"users" – list of identified users
"schemas" – list of identified schemas
"tokens" – list of identified tokens
"topics" – hierarchical structure of Hedera topics and messages relevant to the target document
{
"topicId" – unique topic identifier
"message" – document describing the topic
"messages" – list of documents referenced in the topic
"children" – child topics
}
}
```

### **POST**

* Target document identification based on message ID - the system creates the report on the document which is referenced in the Header message with the specified ID (the presence of the document in the local Guardian database is not required)

```
{
"filterValue": "hedera message id"
}
```

* Target document identification by its hash – they system build the report on the document in the local DB which has the specified hash

```
{
"filterValue": "hash"
}
```

* Resets the report

```
{
"filterValue": "",
}
```

## 2. Example

Block can work independently (stand-alone):

![image2.png](/files/05ewmeLaUKRjpb5O2W3K)

Or used in conjunctions with other blocks (e.g. with grid)

![image3.png](/files/WNfCnAekCcFtvxagYKKJ)

### **2.1 Display** **Modes**

#### **2.1.1 Simplified** – folds all messages for a policy into a single ‘swim lane’.

* Only policy topics are displayed
* Auxiliary events (such as publishing policy) are hidden

![image4.png](/files/nrfLuCi6KfAxVNRmSG77)

#### **2.1.2 Advanced** – complete information is displayed with

* Full hierarchical topic structure
* All auxiliary and system events

![image5.png](/files/TpmhjgaXRHBGNOHXj4lW)

#### **2.1.3 Display layout**

* Left-side panel shows hierarchical catalog of Header topics.

![image6.png](/files/lXZLbthIvlHZJDIsPKad)

* Central area shows the timeline of the events as they have been recorded (in messages) in the specific topics

![image5.png](/files/TpmhjgaXRHBGNOHXj4lW)

* Right-side panel shows detailed information about the selected message

![image1.png](/files/QIZXi1f6VcL2U38quLNL)


# notificationBlock

This Block is used to generate Notifications.

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

## 1.1 Properties

| Property Name               | Description                                                                                           | Example                                                                      | Status |
| --------------------------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ------ |
| Tag                         | Unique name for the logic block.                                                                      | notificationBlock                                                            |        |
| Permissions                 | Which entity has rights to interact at this part of the workflow.                                     | Standard Registry                                                            |        |
| Default Active              | 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                                                         |        |
| On Errors                   | Called if the system error occurs in the Block                                                        | <p>- No action<br>- Retry</p>                                                |        |
| Title                       | .Notification title                                                                                   | Schema Creation                                                              |        |
| Type                        | type of notification                                                                                  | ERROR, SUCCESS, INFO, WARN                                                   |        |
| Message                     | Notification message                                                                                  | Schema is created                                                            |        |
| Link notification to policy | If checked : policy will be opened by clicking on notification                                        | Checked or Unchecked                                                         |        |
| User                        | If User == “ROLE”, users can setup appropriate role and also mark it as “Only for current user group” | ALL,CURRENT,POLICY\_OWNER,DOCUMENT\_OWNER,DOCUMENT\_ISSUER,GROUP\_OWNER,ROLE |        |


# Button Block Addon (buttonBlockAddon)

The purpose of this block is to display interactive buttons in documents source block (interfaceDocumentsSourceBlock).

## Usage

As shown in the example below, buttonBlockAddon blocks should be placed inside interfaceDocumentsSourceBlock blocks.

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

## Properties

<table><thead><tr><th>Property Name</th><th>Description</th><th width="243">Example</th><th>Status</th></tr></thead><tbody><tr><td>Button Name (<em>name</em>)</td><td>The label (name) of the button as displayed to the user</td><td>"Approve", "Reject"</td><td></td></tr><tr><td>UI Class (<em>uiClass</em>)</td><td>The UI class of the button</td><td>“btn-approve”, “btn-reject”, “btn-link”</td><td></td></tr><tr><td>hideWhenDiscontinued</td><td>Check if the button should be hidden when policy is discontinued</td><td>Checked/Unchecked</td><td></td></tr><tr><td>Dialog (<em>dialog)</em></td><td>Determines if a dialog should be opened after the button is clicked</td><td>true, false.</td><td></td></tr><tr><td>Dialog Options (<em>dialogOptions</em>)</td><td>Will be shown only if the Dialog setting is set to true.</td><td><ol start="1"><li>Dialog Title (<em>dialogOptions.dialogTitle</em>): The title of the dialog. Example: “Rejection”.</li><li>Dialog Description (<em>dialogOptions.dialogDescription</em>): The description of the dialog. Example: “Enter reject reason”.</li><li>Dialog Result Field Path (<em>dialogOptions.dialogResultFieldPath</em>): The field which will contain the result value from the dialog. Example: “option.comment”.</li></ol></td><td></td></tr></tbody></table>

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

## Events

Button block addon events will be automatically added to document source.

<figure><img src="/files/3cgCsptFT96YyzihFCIN" alt=""><figcaption></figcaption></figure>

## API

The API for the buttonBlockAddon features both GET and POST methods:

1. Example response to the GET request:

```
{
    "id": "4e43f63f-f2e9-4336-a69e-931ec4aafaee",
    "blockType": "buttonBlockAddon",
    "dialog": true,
    "dialogOptions": {
        "dialogTitle": "Reject",
        "dialogDescription": "Enter reject reason",
        "dialogResultFieldPath": "option.comment"
    },
    "name": "Reject",
    "uiClass": "btn-reject",
}

```

The response to the GET request includes all block settings.

2. Example payload for the POST request:

```
{
  "documentId": "66b2838927c34db3c18e3c49",
  "dialogResult": "Typo in name"
}

```

Where

documentId - selected document identifier.

dialogResult is used for the dialog only.


# Dropdown Block Addon (dropdownBlockAddon)

The purpose of this block is to display an interactive dropdown menu in the interfaceDocumentsSourceBlock.

## Usage

As shown in the example below, dropdownBlockAddon blocks should be placed inside interfaceDocumentsSourceBlock blocks. Source addons, which return documents for the dropdown, should be placed inside dropdownBlockAddon.

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

## Properties

| Property Name                | Description                                                                   | Example                             | Status |
| ---------------------------- | ----------------------------------------------------------------------------- | ----------------------------------- | ------ |
| Option Name (*optionName*)   | The label (name) which is shown in dropdown items.                            | document.credentialSubject.0.field0 |        |
| Option Value (*optionValue*) | The value which will be used when a specific item is clicked.                 | document.credentialSubject.0.id     |        |
| Field (*field*)              | The field in selected document which will be populated with the option value. | assignedTo                          |        |

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

## Events

Dropdown block addon events will be automatically added to document source.

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

## API

The API for the dropdownBlockAddon has both GET and POST methods:

1. Example response to the GET request:

```
{
    "id": "47169fdc-900f-4e07-abb4-5510d7be1175",
    "blockType": "dropdownBlockAddon",
    "optionName": "document.credentialSubject.0.field0",
    "optionValue": "document.credentialSubject.0.id",
    "field": "assignedTo",
    "documents": [
        {
            "name": "example",
            "optionValue": "did:hedera:testnet:9XvzF671JeyoVRg8PvSZBTTyKyrvnZu2Mz7qE6FZXY8P_0.0.4481265",
            "value": "66b28683d029375c10f0f4ef"
        }
    ],
}

```

A response to the GET request includes all block settings and:

● documents - Dropdown options

2. Example payload for the POST request:

```
{
  "documentId": "66b28672d029375c10f0f4b6",
  "dropdownDocumentId": "66b28683d029375c10f0f4ef"
}
```

● documentId - Selected document

● dropdownDocumentId - Dropdown item which was clicked


# Request Vc Document Block Addon (requestVcDocumentBlockAddon)

The purpose of this block is to display an interactive button in the interfaceDocumentsSourceBlock.

## Usage

As shown in the example below, requestVcDocumentBlockAddon blocks should be placed inside interfaceDocumentsSourceBlock blocks.

<figure><img src="/files/65zWrbikuQzvI1MLH9yb" alt=""><figcaption></figcaption></figure>

## Properties

| Property Name                  | Description                                                      | Example                                                                                                                                      | Status |
| ------------------------------ | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| Button Name (*buttonName*)     | The label (name) of the button as displayed to the user.         | Add report                                                                                                                                   |        |
| UI Class (*uiClass*)           | The UI class of the button.                                      | "btn-approve”, “btn-reject”, “btn-link                                                                                                       |        |
| hideWhenDiscontinued           | Check if the button should be hidden when policy is discontinued | Checked/Unchecked                                                                                                                            |        |
| Dialog Title (*dialogTitle*)   | The title of the dialog.                                         | Add report                                                                                                                                   |        |
| Schema (*schema*)              | Schema which will be used for document creation.                 | #de62118a-d746-4c9f-ba1a-2278b13a2137                                                                                                        |        |
| Id Type (*idTypev)*            | Type of identifier in document which will be created.            | “UUID”, “DID”, “OWNER”                                                                                                                       |        |
| Preset (*preset*)              | Will selected document be used as preset.                        | true, false                                                                                                                                  |        |
| Preset Schema (*presetSchema*) | Schema which will be used as a preset schema.                    | #de62118a-d746-4c9f-ba1a-2278b13a2137                                                                                                        |        |
| Preset Fields (*presetFields*) | Preset fields configuration.                                     | <p>\[</p><p>{</p><p>"name": "field0",</p><p>"title": "Project Details",</p><p>"value": "field0",</p><p>"readonly": false</p><p>}</p><p>]</p> |        |

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

## Events

Request VC document block addon events will be automatically added to document source.

<figure><img src="/files/9zX7AOuSpjhOMy8wugYM" alt=""><figcaption></figcaption></figure>

## API

The API for the dropdownBlockAddon has both GET and POST methods:

1\. Example response to the GET request:

```
{
  "id": "20639b5d-c43d-4aa0-a1d1-d0ac36e867de",
  "blockType": "requestVcDocumentBlockAddon",
  "buttonName": "Add Report",
  "uiClass": "link",
  "dialogTitle": "Add Report",
  "presetFields": [
    {
      "name": "field0",
      "title": "Project Details",
      "value": "field0",
      "readonly": false
    },
	...
  ],
  "schema": {
    ...
  },
  "idType": "UUID",
  "preset": true,
  "presetSchema": "#de62118a-d746-4c9f-ba1a-2278b13a2137",
}

```

A response to the GET request includes all block settings and:

● schema - Schema document

2. Example payload for the POST request:

```

 	  "document": {
    "field0": "Device",
    "field1": "Organization",
    ...
  },
  "ref": "66ba0cad0edaef237a78b44b"
}

```

● document - Credential subject

● ref - Reference document identifier


# Data Transformation Addon

The purpose of this block is to produce a transformed result based on the data from the source

and filters blocks.

This block can be used in conjunction with pagination and filters for the

source block.

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

## Usage

As shown in the example below, dataTransformationAddon blocks should be placed after

documentsSourceAddon and filtersAddon blocks.

<figure><img src="/files/03rNvp3Xitz3Fz45YERO" alt=""><figcaption></figcaption></figure>

## Properties

| Property Name        | Description                                                                                                                            | Example                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Expression           | <p>A custom JavaScript</p><p>function that transforms</p><p>the existing source data</p><p>and returns it in a</p><p>custom format</p> | <p><code>function main(documents){</code></p><p><code>let sum = 0;</code></p><p><code>for(let i=0; i< documents.length; i++) {</code></p><p><code>sum+=</code></p><p><code>documents\[i].document.credentialSubject\[0].fiel</code></p><p><code>d0 +</code></p><p><code>d1;</code></p><p><code>documents\[i].document.credentialSubject\[0].fiel</code></p><p><code>}</code></p><p><code>return {</code></p><p><code>sum</code></p><p><code>}</code></p><p><code>}</code></p><p><code>done(main(documents));</code></p> |
| hideWhenDiscontinued | Check if the button should be hidden when policy is discontinued                                                                       | Checked/Unchecked                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |

## API

The API for the dataTransformationAddon uses the GET method

Example response to a GET request that returns the sum of 2 fields in a custom format:

```
{
"sum": 10
}
```

The request can be fulfilled through both endpoint

*`/api/v1/policies/{policyId}/blocks/{blockId}`*

and

*`/api/v1/policies/{policyId}/tag/{blockTag}/blocks`*


# IntegrationButtonBlock

The purpose of this block is to enable interaction with third-party data providers through configurable parameters and caching mechanisms.

Below is a description of the available options and supported services:

## 1.1 Properties <a href="#id-1.1-properties" id="id-1.1-properties"></a>

<table><thead><tr><th>Property Name</th><th width="269.6015625">Description</th><th>Example</th></tr></thead><tbody><tr><td>Button name</td><td>The display name of the button</td><td>Integration Data</td></tr><tr><td>Enable caching</td><td>If set to true, and the data was previously saved to the database (e.g., via the "sendToGuardian" block), future requests with the same parameters will retrieve the data from the cache instead of performing a new request.</td><td>Checked/unchecked</td></tr><tr><td>Integration</td><td><p>Type of integration. Currently supported values:</p><ul><li>GLOBAL_FOREST_WATCH</li><li>KANOP_IO</li><li>WORLD_BANK</li><li>FIRM</li></ul></td><td>KANOP_IO</td></tr><tr><td>hideWhenDiscontinued</td><td>Check if the button should be hidden when policy is discontinued</td><td>Checked/Unchecked</td></tr><tr><td>Request type</td><td>The name of the specific request to execute (varies per integration).</td><td>getDatasets</td></tr><tr><td>Request params</td><td>Parameters required for the selected request. These are integration-specific.</td><td>datasets</td></tr></tbody></table>

<figure><img src="https://docs.hedera.com/guardian/~gitbook/image?url=https%3A%2F%2F1556785885-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FNYWPEEAknX9Vki1yV5HY%252Fuploads%252FIagZQVulGgAMVzRwvKGL%252Fimage.png%3Falt%3Dmedia%26token%3Dfeb0ba56-aa6c-4113-9c0e-982cd327b4d8&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=bcd756be&#x26;sv=2" alt=""><figcaption></figcaption></figure>

## 1.2 Output Events <a href="#id-1.2-output-events" id="id-1.2-output-events"></a>

This block can emits the following events:

* RunEvent
* ReleaseEvent
* RefreshEvent

<figure><img src="https://docs.hedera.com/guardian/~gitbook/image?url=https%3A%2F%2F1556785885-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FNYWPEEAknX9Vki1yV5HY%252Fuploads%252FShQR7hOiHrSkgf1lcBIK%252Fimage.png%3Falt%3Dmedia%26token%3Dd7902a14-392c-4bf4-a69b-d27842a90cad&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=b08eb688&#x26;sv=2" alt=""><figcaption></figcaption></figure>

To enable caching functionality, data must be saved to the database using the "sendToGuardian" block with the source set to auto or database. You can link the IntegrationButton to the "sendToGuardian" block using the RunEvent output event.

<figure><img src="https://docs.hedera.com/guardian/~gitbook/image?url=https%3A%2F%2F1556785885-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FNYWPEEAknX9Vki1yV5HY%252Fuploads%252FkAHcZs6ia2IQT1ndhREY%252Fimage.png%3Falt%3Dmedia%26token%3D4c90437a-c575-4389-b88f-1e580c2117af&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=dbaffe2c&#x26;sv=2" alt=""><figcaption></figcaption></figure>

## 1.3 Supported Integrations <a href="#id-1.3-supported-integrations" id="id-1.3-supported-integrations"></a>

This block supports four third-party data providers:

1\. [Global Forest Watch](https://data-api.globalforestwatch.org/)

2\. [Kanop](https://www.kanop.io/)

3\. [World Bank Governance Indicators](https://databank.worldbank.org/source/worldwide-governance-indicators)

4\. [NASA FIRMS](https://firms.modaps.eosdis.nasa.gov/)

<figure><img src="https://docs.hedera.com/guardian/~gitbook/image?url=https%3A%2F%2F1556785885-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FNYWPEEAknX9Vki1yV5HY%252Fuploads%252Feqoda6K0NQWTeRuixYF7%252Fimage.png%3Falt%3Dmedia%26token%3De32c1907-92a6-409c-866e-5ef54955d5a3&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=d5408100&#x26;sv=2" alt=""><figcaption></figcaption></figure>

## 1.4 Request UI Parameters <a href="#id-1.4-request-ui-parameters" id="id-1.4-request-ui-parameters"></a>

Each integration has a list of supported requests and associated parameters. For each request parameter, two input methods are available:

| Parameter          | Description                                                   |
| ------------------ | ------------------------------------------------------------- |
| Path field for ... | A Path input to extract data from an existing field.          |
| Value for ...      | A manual input for static values (e.g., known dataset names). |

{% hint style="info" %}
**Note: If both fields are filled, "Value for ..." takes precedence.**
{% endhint %}

<figure><img src="https://docs.hedera.com/guardian/~gitbook/image?url=https%3A%2F%2F1556785885-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FNYWPEEAknX9Vki1yV5HY%252Fuploads%252FhB05XVxFlflvB1Qi0UhN%252Fimage.png%3Falt%3Dmedia%26token%3De26ca44b-e9b5-42ec-b8bf-3adc5016a30f&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=58027a6c&#x26;sv=2" alt=""><figcaption></figcaption></figure>


# Global Events Writer Block

Publishes document references to one or more global Hedera topics.

* Publishes reference/metadata only (does not create, update, or re-anchor the document).
* Can publish to multiple global topics.
* Publishes each time the block is executed in the policy flow.
* Lets you control publishing per topic/stream in the Writer UI:
* Active ON/OFF — ON = publish, OFF = skip.
* Hidden (optional) — stays in configuration but is hidden in UI.
* Document Type — set per-topic type (vc/json/csv/text/any).

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

## 1.1 Properties

| Property Name                          | Description                                                                                               | Example           |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------- | ----------------- |
| Default Active(in the block Meta Data) | controls the visibility in the runtime UI                                                                 | Checked/Unchecked |
| Show Next button                       | enable to use this block inside a Step container                                                          | Checked/Unchecked |
| Global topics                          | the list of default topicIds that Admin adds to the block configuration                                   | 0.0.7559767       |
| Active by default                      | controls the visibility                                                                                   | Checked/Unchecked |
| Document type                          | which documentType the Writer writes into the event message for this topic (VC / JSON / CSV / TEXT / ANY) | VC                |

<figure><img src="/files/3RR3fpPzO6a5iMmiIXNX" alt=""><figcaption></figcaption></figure>

## 1.2 API

* Uses the standard policy blocks API (setData), same as other blocks.
* Reader/Writer don’t introduce a new API — they only define their own payload format and supported operation values.

```
Writer payload (Update streams):
{
  "operation": "Update",
  "streams": [
    { "topicId": "0.0.45345345", "documentType": "vc", "active": true }
  ]
}
```


# Global Events Reader Block

Subscribes to global topics and routes incoming events into policy branches.

* Can subscribe to multiple global topics.
* Reads/handles messages only from topics with Active = ON (OFF = ignore this topic).
* Lets you control subscriptions per topic/stream in the Reader UI:
* Active ON/OFF — ON = read/process, OFF = ignore.
* Hidden (optional) — stays in configuration but is hidden in UI.
* Routes an event into a branch only if validations pass:
* Document type matches branch configuration.
* If configured, the schema matches / validates for that branch.
* If applicable, field filters match.
* Applies filters only for VC, and only when Admin configured a schema for the branch.

## 1.1 Properties

| Property Name                           | Description                                                             | Example                  |
| --------------------------------------- | ----------------------------------------------------------------------- | ------------------------ |
| Default Active (in the block Meta Data) | controls the visibility in the runtime UI                               | Checked/Unchecked        |
| Show Next button                        | enable to use this block inside a Step container.                       | Checked/Unchecked        |
| Global topics                           | the list of default topicIds that Admin adds to the block configuration | 0.0.750....              |
| Active by default                       | controls the visibility of topicID                                      | Checked/Unchecked        |
| Branch event                            | output event name to trigger                                            | branch 1                 |
| Document type                           | expected type for this branch (VC / JSON / CSV / TEXT / ANY)            | VC                       |
| Schema (optional)                       | local policy schema used for VC validation before routing.              | Registrant & Participant |

<figure><img src="/files/0JPqtB6366nrZUMKmHB5" alt=""><figcaption></figcaption></figure>

* Events tab - setting output events to the branches.

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

## 1.2 API

* Uses the standard policy blocks API (setData), same as other blocks.
* Reader/Writer don’t introduce a new API — they only define their own payload format and supported operation values.

```
Reader payload (Update streams):
{
  "operation": "Update",
  "value": {
    "streams": [
      {
        "globalTopicId": "0.0.7559767",
        "active": true,
        "branchDocumentTypeByBranch": { "branch 1": "vc", "branch 2": "vc" },
        "filterFieldsByBranch": {}
      }
    ]
  }
}
```


# mathBlock

The *mathBlock* (also known as *formula calculation block or FCB*) lets you to define calculations on document data in mathematical notation to be performed directly, without the need or optionally with limited use of coding.

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

## 1.1 Properties

|               |                                                                                             |                       |
| ------------- | ------------------------------------------------------------------------------------------- | --------------------- |
| Input Schema  | The input document schema.Required                                                          | Net\_ERR\_Calculation |
| Output Schema | The output (results) document schema. Optional. If not specified, the input schema is used. | Net\_ERR\_Calculation |
| Unsigned VC   | Allows the use of a simple JSON document as input (no VC-style proofs required)             | Checked/Unchecked     |
| Expression    | The set of formulas and commands executed at policy runtime.                                | formulas defined      |

## 1.1.1 Expression definition

Expression definition is guided by a wizard with in-place test execution, allowing policy authors to define formulas and the data they apply to at policy runtime. It includes the following sections:

#### 1. Inputs

Use this section to map fields from the input document to short variable names that you can reference in formulas.

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

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

{% hint style="info" %}
**Note 1**: A variable in a formula may reference data from any field in any document, not just the input document itself. However, the referenced document must be associated with the input document (i.e. be part of its 'relationships' chain). If no such relationship exists, the value cannot be resolved at runtime, which may lead to unpredictable or undefined behavior.
{% endhint %}

{% hint style="info" %}
**Note 2**: Source documents are located based on schema matching. If multiple related documents match the required schema, the system selects the nearest (most recent) document in the relationships chain as the data source.
{% endhint %}

### 2. Formulas

This section provides UI to defined formulas using standard mathematical notation and/or LateX or MathJSON formats.

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

**2.1 Formula definition**

To define a formula, complete the following steps:

* Specify the formula name.
* Add () after the formula name and list any parameters inside. Separate parameters with a comma (,).

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

* Create the expression using math notation or an alternative format (LaTeX, MathJSON).

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

In some cases, switching between math notation, LaTeX and MathJSON can help you verify or correct a formula. You can edit in any format; the system automatically synchronizes changes across formats.

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

You can reuse defined formulas in other formulas (by name) and in the code on the Advanced tab.

{% hint style="success" %}
**Note**: Not all commands supported in math notation are represented correctly in LaTeX. In LaTeX view, unsupported commands may appear as plain strings. For the complete list of commands supported by Guardian in math notation, see the MathLive Compute Engine standard library documentation: <https://mathlive.io/compute-engine/standard-library>
{% endhint %}

{% hint style="success" %}
**Note**: The single-letter names `i` and `e` are reserved by the Compute Engine. Single-letter names used as variable inputs (e.g. `A`, `R`) must appear **without** `\mathrm{}` wrapping in formulas — use bare `A`, `R` rather than `\mathrm{A}`, `\mathrm{R}`.
{% endhint %}

**2.2 Variables**

When parentheses are not included after the name (e.g., x vs. x()), it is treated as a variable definition. The variable value is calculated at initialization time.

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

**2.3 Supported Compute Engine Functions**

Guardian formulas run on the MathLive Compute Engine. The following standard CE functions have been verified to work correctly in Guardian formulas.

**Array functions**

| Function | LaTeX                                                                | Description                                                                                                       |
| -------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `Map`    | `\mathrm{Map}\left(1..N,\ \mathrm{index} \mapsto \text{expr}\right)` | Applies an expression to each index from `1` to `N` and returns the resulting array.                              |
| `At`     | `\mathrm{At}\left(\mathrm{arr},\ \mathrm{index}\right)`              | Returns the element at 1-based position `index` from array `arr`. Used inside `Map` to access per-element values. |
| `Length` | `\mathrm{Length}\left(\mathrm{arr}\right)`                           | Returns the number of elements in array `arr`. Typically used as the upper bound in `Map` or `Sum`.               |
| `Sum`    | `\sum_{n=1}^{N} \text{expr}`                                         | Sums an expression over an index range.                                                                           |

**Math functions**

| Function | LaTeX                            | Description                        |
| -------- | -------------------------------- | ---------------------------------- |
| `Max`    | `\mathrm{Max}\left(a,\ b\right)` | Returns the larger of two values.  |
| `Min`    | `\mathrm{Min}\left(a,\ b\right)` | Returns the smaller of two values. |
| `Power`  | `base^{exp}`                     | Raises `base` to the power `exp`.  |

**Logic functions**

| Function | LaTeX                                         | Description                                                                                                                                                                                                                                          |
| -------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Boole`  | `\mathrm{Boole}\left(\text{condition}\right)` | Returns 1 if the condition is true, 0 otherwise. Use as a numeric multiplier to conditionally include a term. The condition can be written as an operator (At(qaVal, index) = 1) or as an explicit Equal call (Equal(At(arr1, n), At(arr2, index))). |
| `Equal`  | `a = b`                                       | Returns true if `a` equals `b`. Works correctly for numbers and for string elements retrieved from arrays via `At()`. For scalar string input fields use `EqualString` instead (see section 2.4).                                                    |
| `Not`    | `\mathrm{Not}\left(\text{condition}\right)`   | Negates a boolean condition.                                                                                                                                                                                                                         |

**Example — computing a value per instance:**

```latex
\mathrm{Map}\left(1..\mathrm{Length}\left(\mathrm{plantingCohort}\right),\ \mathrm{index} \mapsto
  \mathrm{At}\left(\mathrm{CWPwoodyABt},\ \mathrm{index}\right) \times \left(1 + \mathrm{At}\left(R,\ \mathrm{index}\right)\right)
\right)
```

**Example — summing array elements that match a condition:**

```latex
\sum_{n=1}^{\mathrm{Length}\left(\mathrm{qaVal}\right)} \mathrm{Boole}\left(\mathrm{At}\left(\mathrm{qaVal},\ n\right) = 1\right)
```

**Example — conditionally including a term based on a flag:**

```latex
\mathrm{Boole}\left(\mathrm{At}\left(\mathrm{eqIsArea},\ \mathrm{index}\right) = 1\right) \times \mathrm{At}\left(\mathrm{eqCWPt},\ \mathrm{index}\right)
```

{% hint style="warning" %}
**Known unsupported or unreliable functions**: `Reduce` with `Add` does not work reliably — use `\sum` instead. `IndexWhere` is not supported. `If` and `Which` as standalone return values produce empty results — replace conditionals with `Boole` multiplied terms instead (e.g. `Boole(cond) * val1 + Boole(Not(cond)) * val2`).
{% endhint %}

**2.4 Built-in Lookup Functions**

Guardian provides the following built-in functions for looking up values in arrays by key. These are particularly useful when working with per-instance data arrays (e.g. one row per instance).

| Function      | Signature                                   | Description                                                                                                                                                                                |
| ------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Lookup`      | `Lookup(values, keys, id)`                  | Returns the value at the first position where `keys[i] == id`. Returns `0` if not found.                                                                                                   |
| `LookupTwo`   | `LookupTwo(values, keys1, id1, keys2, id2)` | Returns the value where both `keys1[i] == id1` and `keys2[i] == id2`. Useful for matching on two dimensions (e.g. instance + year). Returns `0` if not found or if array lengths differ.   |
| `LookupMin`   | `LookupMin(values, keys, id, sortKeys)`     | Among all rows where `keys[i] == id`, returns the value with the minimum `sortKeys[i]`. Useful for selecting the earliest year value. Returns `0` if not found.                            |
| `LookupMax`   | `LookupMax(values, keys, id, sortKeys)`     | Among all rows where `keys[i] == id`, returns the value with the maximum `sortKeys[i]`. Useful for selecting the most recent value when data has multiple years. Returns `0` if not found. |
| `EqualString` | `EqualString(a, b)`                         | Returns `1` if `a` and `b` are equal as strings, `0` otherwise. Use this instead of `Equal` when comparing string-typed input fields (e.g. `Yes`/`No`).                                    |

**Example usage in LaTeX:**

```latex
\mathrm{Lookup}\left(\mathrm{CWPwoodyABt},\ \mathrm{CWPwoodyABtId},\ \mathrm{At}\left(\mathrm{plantingCohort},\ \mathrm{index}\right)\right)
```

```latex
\mathrm{LookupMax}\left(\mathrm{mt},\ \mathrm{mtId},\ \mathrm{At}\left(\mathrm{plantingCohort},\ \mathrm{index}\right),\ \mathrm{mtYear}\right)
```

```latex
\mathrm{EqualString}\left(\mathrm{biomassBurningBoundary},\ \text{Yes}\right)
```

{% hint style="info" %}
**When to use `Lookup` vs `LookupMax`**: Use `Lookup` for parameters that have a single value per instance (no `year` field in the source data). Use `LookupMax` for monitored parameters that may have multiple yearly measurements — it selects the most recent one. Use `LookupMin` to select the earliest.
{% endhint %}

{% hint style="warning" %}
**Important — NaN propagation**: All lookup functions return `0` (not `NaN`) when no match is found. This is intentional: the Compute Engine evaluates all subexpressions immediately, so a `NaN` result from a lookup would propagate through any arithmetic that uses it (e.g. `NaN * 0 = NaN`), corrupting downstream calculations. Returning `0` ensures that expressions gated by a flag multiplied by `0` correctly produce `0` rather than `NaN`.
{% endhint %}

{% hint style="warning" %}
**String comparison**: The standard `Equal` operator works for numeric values and for string elements retrieved from arrays via `At()`. However, for scalar string input fields (e.g. `Yes`/`No`), use `EqualString` instead of `Equal`. `Equal` on a string scalar produces unexpected results because the Compute Engine stores scalar strings as symbols rather than string literals.
{% endhint %}

**2.5 Code (advanced)**

For complex scenarios where formulas are not sufficient for the required data transformations, use the Advanced (Optional) tab to add logic in JavaScript.

<figure><img src="/files/20YHBYTAXOUiiWKYnsIq" alt=""><figcaption></figcaption></figure>

In code, you can reference all defined formulas and variables by name.

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

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

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

{% hint style="info" %}
**Note — JavaScript execution order**: The JavaScript code section executes **after** all formula variables have been evaluated. This means JavaScript can read formula results but cannot influence formula evaluation. Use JavaScript for post-processing tasks such as filtering arrays by a condition, aggregating results across instances or writing values that depend on multiple formula outputs. Avoid duplicating mathematical logic in JavaScript that can be expressed in formulas.
{% endhint %}

### 3. Outputs

Use this section to configure which document fields receive the results of calculations from the previous sections.

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

In this section, you can reference input/output fields and variables only. Formulas can be referenced only in the Formulas section.

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

{% hint style="warning" %}
**Note — Output type constraint**: Only variables of type `variable` (not `function`) can be mapped to output fields. If a formula result needs to be written to an output, wrap it in an intermediate variable first.
{% endhint %}

### 4. Tabs

For convenience Inputs\Formulas\Outputs can be visually partitioned using tabs. This partitioning has not impact on the functionality of the policy, it is used to ease UI navigation by policy authors.

#### 4.1 Creation

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

#### 4.2 Renaming

Tabs can be renamed as required.

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

#### 4.3 Deletion

Tabs can be deleted.

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

#### 4.4 Navigation

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

### 5. Test

After you define formulas, you can validate them using the Test section. Complete the following steps:

#### a. Inputs

To begin testing, specify the main Input Document.

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

If required, add additional documents associated with the input document. Make sure these documents are part of the main Input Document's relationships chain.

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

Provide input data in a document using one of the following three options:

* Use a form that matches the input schema.

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

* Provide JSON.

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

* Upload a file (the file must contain valid JSON).

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

{% hint style="info" %}
**Note — Test button scope**: The Test button executes formulas entirely within the frontend. It does not invoke the policy-service. This means test results reflect formula evaluation only.
{% endhint %}

#### b. Select Test

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

#### c. Results

Guardian displays test results for each element

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

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

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

## 1.2 Visualization at Policy runtime

Once a policy is published, Guardian generates Formula-Linked Definitions (FLDs) for all mathBlock elements in the policy. You can explore these the same way as standard FLDs.

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

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

{% hint style="warning" %}
**Note:** The *mathBlock* code section is not used when automatically generating FLDs and is not represented in any way in the resulting visuals.
{% endhint %}

## 1.3 Known Limitations

| Limitation                                                                                         | Workaround                                                                                                  |
| -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| Single-letter variable names (`A`, `R`, etc.) must not be wrapped in `\mathrm{}` in formula bodies | Use bare `A`, `R` in expressions; only multi-character names need `\mathrm{}`                               |
| `Equal` does not work reliably for scalar string fields (e.g. `Yes`/`No` flags)                    | Use `EqualString(field, "Yes")` instead                                                                     |
| The JavaScript code section runs **after** formula evaluation                                      | Do not rely on JavaScript to set values that formulas will consume; use JavaScript only for post-processing |
| Output fields can only reference `variable` type items, not `function` type                        | Wrap formula results in intermediate variables before mapping to outputs                                    |
| `Reduce` with `Add` does not work reliably for summing arrays                                      | Use `\sum_{n=1}^{N}` syntax instead                                                                         |
| `If` and `Which` as standalone return values produce empty results                                 | Split conditionals into `Boole`-multiplied terms (e.g. `Boole(cond) * val1 + Boole(Not(cond)) * val2`)      |


# API Execution Payloads

This guide documents how external systems interact with Guardian policy blocks through the REST API. It is the primary reference for integrators building MRV data pipelines, verification systems, or any application that submits data into a Guardian policy.

## Overview

A Guardian policy is a directed graph of blocks. External systems interact with blocks through three patterns:

| Pattern            | Method | URL                                            | When to use                                               |
| ------------------ | ------ | ---------------------------------------------- | --------------------------------------------------------- |
| Read block state   | GET    | `/api/v1/policies/{policyId}/blocks/{blockId}` | Get current form schema, document list, or block UI state |
| Submit data        | POST   | `/api/v1/policies/{policyId}/blocks/{blockId}` | Submit a form, trigger a button, select a role            |
| Push external data | POST   | `/api/v1/external/{policyId}/{blockTag}`       | Push MRV/oracle data without a Guardian user session      |

## Authentication

All block API calls require a JWT Bearer token from `POST /api/v1/accounts/login`.

```http
Authorization: Bearer <jwt_token>
```

The calling user must have been assigned the appropriate role within the policy.

***

## Standard Block Response Envelope

When calling `GET /policies/{policyId}/blocks/{blockId}`, Guardian returns a block-specific response. All responses share these common fields:

| Field      | Type    | Description                                                     |
| ---------- | ------- | --------------------------------------------------------------- |
| id         | string  | Block UUID                                                      |
| blockType  | string  | Block type identifier from `BlockType` enum                     |
| policyId   | string  | Owning policy ID                                                |
| readonly   | boolean | Whether the calling user can submit data to this block          |
| uiMetaData | object  | Block-specific display configuration (title, description, type) |

***

## Block Data Submission Response

When calling `POST /policies/{policyId}/blocks/{blockId}` or `POST /policies/{policyId}/tag/{tagName}/blocks`, Guardian acknowledges the submission synchronously and returns a response that includes a `trackingId` for correlating the request with the async completion event.

| Field      | Type   | Description                                                                                                                                                                                                      |
| ---------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| trackingId | string | UUID that uniquely identifies this block execution. Matches the `trackingId` in the `external-events.block_complete` event, allowing external systems to correlate requests with async outcomes without polling. |
| response   | object | Present when `history=true`. The direct output of `blockSetData`.                                                                                                                                                |
| result     | object | Present when `history=true`. The final result from the last downstream step.                                                                                                                                     |
| steps      | array  | Present when `history=true`. Ordered list of intermediate step results across the async execution chain. Empty array when `history` is not requested.                                                            |

**Example response (default):**

```json
{
  "trackingId": "550e8400-e29b-41d4-a716-446655440000"
}
```

**Example response with `history=true`:**

```json
{
  "trackingId": "550e8400-e29b-41d4-a716-446655440000",
  "response": { "...": "blockSetData output" },
  "result": { "...": "last step result" },
  "steps": [
    { "...": "step 1 result" },
    { "...": "step 2 result" }
  ]
}
```

> The submission response is returned as soon as the block accepts the data. The full async chain (IPFS uploads, HCS message submissions, downstream block execution) continues in the background and is reported via the `external-events.block_complete` event.

***

## Block-Specific Payloads

### `requestVcDocumentBlock`

Presents a data entry form based on a schema. The user fills the form and submits a VC document.

**GET response — block state:**

```json
{
  "id": "block-uuid",
  "blockType": "requestVcDocumentBlock",
  "uiMetaData": {
    "type": "page",
    "title": "Installer Registration",
    "description": "Fill in your facility details"
  },
  "schema": {
    "$id": "#installer-schema-uuid",
    "title": "Installer Application",
    "type": "object",
    "properties": {
      "field0": { "title": "Organization Name", "type": "string" },
      "field1": { "title": "Country", "type": "string" },
      "field2": { "title": "Facility Name", "type": "string" },
      "field3": { "title": "Installed Capacity (MW)", "type": "number" }
    },
    "required": ["field0", "field1", "field2"]
  },
  "presetSchema": null,
  "presetFields": []
}
```

**POST request — submit document:**

```json
{
  "document": {
    "credentialSubject": [
      {
        "type": "#installer-schema-uuid",
        "field0": "Acme Energy Corp",
        "field1": "Kenya",
        "field2": "Nairobi Solar Farm 1",
        "field3": 10.5
      }
    ]
  },
  "ref": null
}
```

| Field                      | Type   | Required | Description                                            |
| -------------------------- | ------ | -------- | ------------------------------------------------------ |
| document                   | object | Yes      | VC document to submit                                  |
| document.credentialSubject | array  | Yes      | Array with one object containing schema-defined fields |
| ref                        | string | No       | Parent document ID for relationship linking            |

***

### `uploadVcDocumentBlock`

Accepts file uploads or pre-built VC documents.

**POST request:**

```json
{
  "document": {
    "credentialSubject": [
      {
        "type": "#mrv-schema-uuid",
        "field0": 0.0,
        "field1": 1250.5,
        "field2": "MWh",
        "field3": "2025-01-01",
        "field4": "2025-12-31"
      }
    ]
  }
}
```

***

### `interfaceDocumentsSourceBlock`

Displays a list of documents to the user. Read-only; no POST required.

**GET response:**

```json
{
  "id": "block-uuid",
  "blockType": "interfaceDocumentsSourceBlock",
  "data": [
    {
      "id": "doc-id-123",
      "type": "VC",
      "owner": "did:hedera:testnet:...",
      "document": { ... },
      "option": { "status": "WAITING" },
      "createDate": "2026-03-31T08:00:00.000Z"
    }
  ],
  "fields": [
    { "title": "Status", "name": "option.status", "type": "text" },
    { "title": "Created", "name": "createDate", "type": "date" }
  ],
  "total": 1,
  "page": 0,
  "size": 10
}
```

***

### `buttonBlock`

Displays action buttons that trigger workflow transitions (e.g., Approve/Reject).

**GET response:**

```json
{
  "id": "block-uuid",
  "blockType": "buttonBlock",
  "uiMetaData": {
    "buttons": [
      {
        "tag": "approve_btn",
        "name": "Approve",
        "type": "selector",
        "field": "option.status",
        "value": "APPROVED",
        "uiClass": "btn-approve"
      },
      {
        "tag": "reject_btn",
        "name": "Reject",
        "type": "selector",
        "field": "option.status",
        "value": "REJECTED",
        "uiClass": "btn-reject"
      }
    ]
  }
}
```

**POST request — trigger a button:**

```json
{
  "document": {
    "id": "doc-id-123",
    "option": { "status": "WAITING" }
  },
  "tag": "approve_btn"
}
```

| Field    | Type   | Required | Description                                                          |
| -------- | ------ | -------- | -------------------------------------------------------------------- |
| document | object | Yes      | The document to act on (must include `id`)                           |
| tag      | string | Yes      | Button tag to trigger — must match one of `uiMetaData.buttons[].tag` |

***

### `policyRolesBlock`

Assigns a role to the current user within the policy.

**GET response:**

```json
{
  "id": "block-uuid",
  "blockType": "policyRolesBlock",
  "uiMetaData": { "title": "Select Your Role" },
  "roles": ["Installer", "Standard Registry", "Auditor"]
}
```

**POST request — select role:**

```json
{
  "role": "Installer"
}
```

| Field | Type   | Required | Description                                                             |
| ----- | ------ | -------- | ----------------------------------------------------------------------- |
| role  | string | Yes      | Role name — must be one of the values in the GET response `roles` array |

***

### `mintDocumentBlock`

Mints environmental asset tokens after document approval. This is a server-side block (`post: false`, `get: false`) — it is triggered automatically by the policy engine when an upstream block fires a `RunEvent`. There is no direct GET or POST available from the API.

The block calculates a token amount by evaluating the configured rule expression against the incoming VC documents, creates a mint VC and VP, publishes both to HCS, and calls the Hedera token service to mint the tokens to the target account.

To observe mint outcomes, query the `interfaceDocumentsSourceBlock` that follows the mint block in the policy flow — documents there will carry a `type` of `"MINT"` once minting completes.

***

### `retirementDocumentBlock`

Retires (wipes) tokens from a holder account. This is a server-side block (`post: false`, `get: false`) — it is triggered automatically by the policy engine when an upstream block fires a `RunEvent`. There is no direct GET or POST available from the API.

The block evaluates the configured rule expression (fungible tokens) or serial number expression (non-fungible tokens) against the incoming VC documents, creates a wipe VC and VP, publishes both to HCS, and calls the Hedera token wipe service.

***

### `createTokenBlock`

Presents a token configuration form that allows a user to define and create a new Hedera token within the policy's token template. The block can also be set to `autorun`, in which case it creates the token automatically without user interaction.

**GET response — token template:**

```json
{
  "id": "block-uuid",
  "blockType": "createTokenBlock",
  "title": "Create Token",
  "description": "Define the token parameters",
  "data": {
    "tokenName": "iREC Token",
    "tokenSymbol": "iREC",
    "tokenType": "fungible",
    "decimals": "2",
    "initialSupply": "0",
    "enableAdmin": true,
    "changeSupply": true,
    "enableFreeze": false,
    "enableKYC": false,
    "enableWipe": true,
    "wipeContractId": null
  }
}
```

Fields already locked by the policy template will be returned in `data` but cannot be overridden in the POST — submit only the fields the policy leaves editable.

**POST request — submit token configuration:**

```json
{
  "tokenName": "iREC Token",
  "tokenSymbol": "iREC",
  "tokenType": "fungible",
  "decimals": "2",
  "initialSupply": "0",
  "enableAdmin": true,
  "changeSupply": true,
  "enableFreeze": false,
  "enableKYC": false,
  "enableWipe": true,
  "wipeContractId": null
}
```

| Field          | Type           | Description                                        |
| -------------- | -------------- | -------------------------------------------------- |
| tokenName      | string         | Human-readable token name                          |
| tokenSymbol    | string         | Short token symbol (e.g. `"iREC"`)                 |
| tokenType      | string         | `"fungible"` or `"non-fungible"`                   |
| decimals       | string         | Decimal precision for fungible tokens (e.g. `"2"`) |
| initialSupply  | string         | Initial supply for fungible tokens (e.g. `"0"`)    |
| enableAdmin    | boolean        | Enables admin key on the token                     |
| changeSupply   | boolean        | Enables supply key (required for minting)          |
| enableFreeze   | boolean        | Enables freeze key                                 |
| enableKYC      | boolean        | Enables KYC key                                    |
| enableWipe     | boolean        | Enables wipe key (required for retirement)         |
| wipeContractId | string \| null | Optional Hedera contract ID to use as wipe key     |

On success the block publishes the new token to HCS, stores the resulting `tokenId` in the policy document's `tokens` map, and fires a `RunEvent` to the next block.

***

### `tokenConfirmationBlock`

Prompts the current user to associate (or dissociate) their Hedera account with a specific token, or to skip the step. This is required before a user can receive minted tokens.

**GET response:**

```json
{
  "id": "block-uuid",
  "blockType": "tokenConfirmationBlock",
  "action": "associate",
  "accountId": "0.0.1234567",
  "tokenName": "iREC Token",
  "tokenId": "0.0.9876543"
}
```

| Field     | Type   | Description                                                                        |
| --------- | ------ | ---------------------------------------------------------------------------------- |
| action    | string | `"associate"` or `"dissociate"` — the operation the user is being asked to confirm |
| accountId | string | The user's Hedera account ID that will be associated                               |
| tokenName | string | Display name of the token                                                          |
| tokenId   | string | Hedera token ID to associate                                                       |

**POST request — confirm association:**

```json
{
  "action": "confirm",
  "hederaAccountKey": "302e020100300506032b657004220420..."
}
```

**POST request — skip:**

```json
{
  "action": "skip"
}
```

| Field            | Type   | Required                          | Description                                                                                         |
| ---------------- | ------ | --------------------------------- | --------------------------------------------------------------------------------------------------- |
| action           | string | Yes                               | `"confirm"` to proceed with the association/dissociation, `"skip"` to bypass                        |
| hederaAccountKey | string | Only when `action` is `"confirm"` | The user's Hedera ED25519 private key (hex or DER-encoded) used to sign the association transaction |

> **Security note:** `hederaAccountKey` is transmitted over HTTPS and used in-process to sign the Hedera association transaction. It is not stored by Guardian.

***

### `externalDataBlock`

Receives data pushed from external systems. This is the block to target with `POST /external/{policyId}/{blockTag}`.

**GET response:**

```json
{
  "id": "block-uuid",
  "blockType": "externalDataBlock",
  "tag": "mrv_data_ingestion"
}
```

**External push via** `POST /api/v1/external/{policyId}/{blockTag}`:

```json
{
  "owner": "did:hedera:testnet:zHcDLGFNTnbmDMkaGEfb5zToJKj4KdwNPJ5mGFNjrEV",
  "policyTag": "iREC_V3_Installer",
  "document": {
    "@context": ["https://www.w3.org/2018/credentials/v1"],
    "type": ["VerifiableCredential"],
    "issuer": "did:hedera:testnet:...",
    "issuanceDate": "2026-03-31T00:00:00.000Z",
    "credentialSubject": [
      {
        "type": "#mrv-schema-uuid",
        "field0": 0.0,
        "field1": 1250.5,
        "field2": "MWh",
        "field3": "2025-01-01",
        "field4": "2025-12-31"
      }
    ]
  }
}
```

| Field                      | Type   | Required | Description                                                |
| -------------------------- | ------ | -------- | ---------------------------------------------------------- |
| owner                      | string | Yes      | DID of the document submitter                              |
| policyTag                  | string | Yes      | Policy tag string (from policy configuration)              |
| document                   | object | Yes      | Full or partial VC document                                |
| document.credentialSubject | array  | Yes      | Array containing one credential subject with schema fields |

***

### `reportBlock`

Generates a trust chain / audit trail view. Read-only.

**GET response:**

```json
{
  "id": "block-uuid",
  "blockType": "reportBlock",
  "uiMetaData": { "title": "Trust Chain Report" },
  "items": [
    {
      "title": "Registration Document",
      "document": { ... },
      "type": "VC",
      "tag": "installer_registration",
      "issuer": "did:hedera:testnet:..."
    },
    {
      "title": "MRV Report",
      "document": { ... },
      "type": "VC",
      "tag": "mrv_submission"
    },
    {
      "title": "Minted Token",
      "tokenId": "0.0.1234567",
      "amount": 1250,
      "type": "TOKEN"
    }
  ]
}
```

***

### `switchBlock`

Routes documents to different workflow paths based on conditions. Evaluated automatically by the policy engine — no external interaction required.

***

### `aggregateDocumentBlock`

Collects multiple documents until a threshold is met, then batches them. Evaluated automatically.

***

### `calculateContainerBlock` / `mathBlock`

Performs arithmetic on document fields. Evaluated automatically.

***

### `sendToGuardianBlock`

Sends a document to the Hedera blockchain (IPFS + HCS). Evaluated automatically after form submission or approval.

***

## External Data Submission API Reference

### POST /api/v1/external/{policyId}/{blockTag}

The primary integration endpoint for external MRV systems, IoT sensors, and oracles.

**Authentication:** Not required for `externalDataBlock` configured as public. JWT required otherwise.

**Path Parameters:**

| Parameter | Type   | Required | Description                                      |
| --------- | ------ | -------- | ------------------------------------------------ |
| policyId  | string | Yes      | Policy MongoDB ID or published policy message ID |
| blockTag  | string | Yes      | Unique tag of the target `externalDataBlock`     |

**Full Request Body Schema:**

```json
{
  "owner": "string — DID of document owner (required)",
  "policyTag": "string — policy tag identifier (required)",
  "document": {
    "@context": ["array of JSON-LD context URLs"],
    "type": ["VerifiableCredential"],
    "issuer": "string — DID of issuer",
    "issuanceDate": "string — ISO 8601 date",
    "credentialSubject": [
      {
        "type": "string — schema type IRI",
        "field0": "value matching schema field type",
        "field1": "...",
        "fieldN": "..."
      }
    ],
    "proof": {
      "type": "string",
      "created": "string",
      "verificationMethod": "string",
      "proofPurpose": "string",
      "jws": "string"
    }
  }
}
```

The `proof` field is optional — Guardian will sign the document if not provided.

**Response 200 OK:**

```json
true
```

**Error Codes:**

| Code | Description                                      |
| ---- | ------------------------------------------------ |
| 400  | Missing required fields                          |
| 404  | Policy or block tag not found                    |
| 422  | Document validation failed against policy schema |
| 500  | Internal server error                            |

***

## Tag-Based Block Access

Blocks can also be accessed by tag name instead of UUID:

```
GET  /api/v1/policies/{policyId}/tag/{tagName}/blocks
POST /api/v1/policies/{policyId}/tag/{tagName}/blocks
```

This is useful when block UUIDs change between policy versions but tags remain stable.

***

## Complete Integration Workflow

### Step 1 — Authenticate

```http
POST /api/v1/accounts/login
Content-Type: application/json

{ "username": "mrv_provider", "password": "securepassword" }
```

```json
{ "accessToken": "eyJhbGciOiJSUzI1NiJ9...", "did": "did:hedera:testnet:..." }
```

### Step 2 — Find Published Policy

```http
GET /api/v1/policies?pageIndex=0&pageSize=10
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
```

Locate the policy by `name` or `policyTag` in the response. Note its `id`.

### Step 3 — Navigate to Roles Block

```http
GET /api/v1/policies/{policyId}/navigation
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
```

Find the `policyRolesBlock` in the block tree. Note its `id`.

### Step 4 — Select Role

```http
POST /api/v1/policies/{policyId}/blocks/{rolesBlockId}
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
Content-Type: application/json

{ "role": "MRV Submitter" }
```

### Step 5 — Get Submission Form Schema

```http
GET /api/v1/policies/{policyId}/blocks/{formBlockId}
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
```

Extract the `schema.properties` to determine which fields to populate.

### Step 6 — Submit Document

```http
POST /api/v1/policies/{policyId}/blocks/{formBlockId}
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
Content-Type: application/json

{
  "document": {
    "credentialSubject": [
      {
        "type": "#schema-uuid",
        "field0": 0.0,
        "field1": 1250.5,
        "field2": "MWh"
      }
    ]
  }
}
```

The response includes a `trackingId` to correlate this submission with its async completion event:

```json
{
  "trackingId": "550e8400-e29b-41d4-a716-446655440000"
}
```

### Step 7 — Track Async Completion

Guardian processes block submissions asynchronously. IPFS uploads, HCS message submissions, and downstream blocks all run after the POST returns. There are two ways to observe completion:

**Option A — Subscribe to `external-events.block_complete` (recommended)**

Configure a webhook or SSE listener for the `external-events.block_complete` event. When the full async chain settles, Guardian emits:

```json
{
  "trackingId": "550e8400-e29b-41d4-a716-446655440000",
  "blockType": "requestVcDocumentBlock",
  "blockTag": "mrv_submission",
  "blockId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
  "policyId": "6475a9e0-5f27-4ce3-b2f1-123456789abc",
  "userId": "did:hedera:testnet:z6MkHmF...",
  "status": "success",
  "timestamp": 1745123456789
}
```

Match the event's `trackingId` to the value returned in Step 6 to confirm your submission completed. When `status` is `"failure"`, the `error` and `errorDetails` fields contain diagnostics.

| Event field  | Type   | Description                                                                                           |
| ------------ | ------ | ----------------------------------------------------------------------------------------------------- |
| trackingId   | string | Matches the value returned by the POST response in Step 6                                             |
| blockType    | string | Block type that processed the submission                                                              |
| blockTag     | string | Block tag identifier                                                                                  |
| blockId      | string | Block UUID                                                                                            |
| policyId     | string | Policy ID                                                                                             |
| userId       | string | DID of the submitting user                                                                            |
| status       | string | `"success"` or `"failure"`                                                                            |
| outputData   | object | Optional. Direct output from `blockSetData` when available                                            |
| error        | string | Optional. Human-readable description of the first error (when `status` is `"failure"`)                |
| errorDetails | array  | Optional. All errors collected across the async chain — each entry has `message` and optional `stack` |
| timestamp    | number | Unix millisecond timestamp when completion was determined                                             |

**Option B — Poll document status**

```http
GET /api/v1/policies/{policyId}/blocks/{viewerBlockId}
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
```

Poll until `data[0].option.status` changes to `APPROVED` or `REJECTED`. Use this when you cannot configure an event listener.


# Creating a Policy Reference

Once you login as a Standard Registry and finish the setup, click on Policies tab.

![](/files/u0AuIzldK3koai5Zcodn)

We have two options to create Policy :

1. Creating Policy from scratch
2. Importing Policy (zip file format)either from file or from IPFS.

### 1. Creating Policy from Scratch

1.1 To create Policy from scratch, we need to click on "Create Policy" button.

![](/files/G9tL6KvNJfj72peovv0Q)

1.2 Once you click on Create Policy , you get a dialog box to fill out basic Policy details.

![](/files/eizVtnpOmXhwGqHvjmy9)

1.3 Once the details are filled and clicked on OK. Initially, Policy is created in Draft status.

![](/files/exKKouXzrsJTXh5WflNX)

1.4 You can even edit the Policy by clicking Edit button.

![](/files/2TVWGCM0ClZJxDVHUA7W)

1.5 When clicked on Edit, the screen is navigated to Policies configuration tab, which gives an option to add/remove any block from the Policy.

![](/files/VdsPph5qkyN3e9Uwa7mx)

1.6 Once the Policy is configured, you can go to Policies tab and click on Publish.

![](/files/ndds00M5ksSNpl3loC75)

### 2. Importing Policy either from File or from IPFS

Instead of creating Policy from scratch, there is an option of importing the Policy zip file from Local system.

{% hint style="info" %}
**Note:** Files with **.policy** extension are only accepted. These files are in zip format, i.e. they are zip archives of the text file.
{% endhint %}

![](/files/Z7kbQzuL6SupljAFPz2D)

2.1 Once the .zip file is selected, we get the Policy Import Review screen. Once everything looks good, click on Import Button.

![](/files/WvypiOuiYc77CkNQ9DkN)

2.2 The Policy can also be imported by importing it from IPFS.

![](/files/8IzN9miihVOvLmEF80ad)

2.3 To do this, you can use the sample policy that we have already uploaded to IPFS by entering the Hedera Message IDs.

```
1655293847.166673000 (new iREC Policy)
```

![](/files/NBvxXDhlB1o5IHfVqpks)

2.4 If the timestamp entered is correct, we get Policy Import Preview screen. If the imported Policy looks good, click on **Import** button.

![](/files/eg2kLwNAdGlS3YrSYiA2)

2.5 Once the Policy is imported, if everything looks good, click on Publish button. Policy will be published and it is represented by changing the status as Published.

![](/files/7cJxnw5MmxT88tywJ6Y8)

2.6 There is also an option to Export the Policy. To export the policy click on Export button. Once, you click on Export, you get Export dialog, where we have two exporting options: Copy message Identifier and saving the Policy as file.

![](/files/CUs66CicnoRQcfE2wNAR)

When you click on Save to file, Policy is exported as a .zip file.

**Note:** While importing tool via file, or policy via file or IPFS, you can change used tools in preview dialog, it will change tools references in schemas and config automatically.

To get complete information about tools, please refer to [Tools](https://github.com/hashgraph/guardian/blob/develop/Methodology%20Library/CDM/Tools/README.md) section.

<figure><img src="/files/15obJ5vCJzPgHqyiFR83" alt=""><figcaption></figcaption></figure>

### 3. Filtering Policies

On the Policy page, it is now possible to filter the policies list by policy name and tags. All available tags are presented in the dropdown list, which you can create using "Create Tag" for each policy, which makes it easier using the filter.

### 4. Select and Delete Multiple Policies

Users can select and delete policies from the Policies table in Guardian UI and also through the API.

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

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

1. Selected items remain selection across pagination.
2. Dependencies are considered when deleting multiple schemas.
   {% endhint %}

### 5. Policy Disconnection

#### 5.1 Disconnecting from a Local Policy

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

After disconnection:

* The policy is removed from your active policies grid and moved to the Disconnected Policies section

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

* All documents created by you within that policy are marked accordingly to inform other policy participants that you have disconnected.

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

The disconnection operation is reversible. If necessary (for example, in case of accidental disconnection), you can reconnect to the policy at any time.

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




---

[Next Page](/llms-full.txt/1)

