Minka Ledger Docs
Explanations

About Statuses

DateResponsibleChanges
July 15, 2024@Luis FidelisInitial version

This document aims to help users managing record statuses.

What is a record status?

Status - meta.status - is a property of records that describe its current state on the system.

Ledger by default creates stores records with status created - except intents, that are initially stored as pending.

Record statuses can be customized by users to adapt their use cases. For example:

  • Managing signers:

    • invited : The signer was invited to join the network
    • active : The signer has activated its account
    • blocked : The signer was blocked due to suspicious activity on the system
    • and so on
  • Managing wallets:

    • suspended: The wallet has been temporarily disabled due to suspicious activity or policy violations.
    • locked: The wallet is temporarily locked, to prevent unauthorized access.
    • and so on
GET /v2/signer/bank-admin
 
{
    hash: '...',
    data: {
        handle: 'bank-admin',
        ...
    },
    meta: {
        ...,
        status: 'active'
    },
    ...
}
GET /v2/wallets/acc:1234 
 
{
    hash: '...',
    data: {
        ...,
        handle: 'acc:1234',
    },
    meta: {
        ...,
        status: 'suspended'
    },
    ...
}

Managing record statuses

Users can manage status of a record within a proof. Proofs should be sent to separate call to

POST /{record}s/{id}/proofs e.g. POST /signers/bank-admin/proofs.

POST /v2/signers/bank-admin/proofs
{
    method: 'ed25519-v2',
    public: '<signer public>',
    digest: '<proof digest>',
    result: '<signature result>',
    custom: {
        moment: '2023-11-27T17:18:13.034Z',
        status: 'blocked'
    }
}
GET /v2/signer/bank-admin
 
{
    hash: '...',
    data: {
        handle: 'bank-admin',
        ...
    },
    meta: {
        ...,
        status: 'blocked'
    },
    ...
}

A proof can also completely remove the current status of a record, by passing the special value null.

POST /v2/signers/bank-admin/proofs
{
    method: 'ed25519-v2',
    public: '<signer public>',
    digest: '<proof digest>',
    result: '<signature result>',
    custom: {
        moment: '2023-11-27T17:20:13.034Z',
        status: null
    }
}
GET /v2/signer/bank-admin
 
{
    hash: '...',
    data: {
        handle: 'bank-admin',
        ...
    },
    meta: {
        proofs: [...],
        owners: [...],
        moment: ...
    },
    ...
}

Managing record statuses with policies

This section uses status policies to define which statuses are valid for a record as well as their quorum. Please, read About Status Policies for keeping up to date with this concept.

POST /v2/policies
 
{
    ...,
    data: {
        handle: 'bank-signer-status',
        schema: 'status',
        record: 'signer',
        filter: {
            schema: 'bank-signer'
        },
        values: [
            {
                quorum: [{
                    $circle: 'admin'
                }]
            }
        ],
        custom: {
            description: 'Policy for any status of a bank signer in ledger'
        }
    }
}

Given the policy above, let's imagine that the following signers, represented by their public keys, are members of circle admin :

  • signer A: WAweF9PHlboQoW0z8NqhZXFmzUTaV74NRFAd/aILprE=
  • signer B: AILprEWWAweF9PHlboQoW0z8NqhZXFmzUTaV74NRFAd=

First, a signer with public key FmzUTaV74NRFAd/aILprE=WAweF9PHlboQoW0z8NqhZX, which is not part of circle admin, tries to update a bank signer status from active to blocked

POST /v2/signers/bank-admin/proofs
 
{
    method: 'ed25519-v2',
    public: 'FmzUTaV74NRFAd/aILprE=WAweF9PHlboQoW0z8NqhZX',
    digest: '4969e3c012b66d88cec597bf337fc01eab8d651e6ed2d5c40236cc1f7d93435a',
    result: '0G2gvSfBx6MwPT8ShBaiYx7zwa5Kqc4Cq3S3NXV1m5/ZPozoH/SUouuhi9sQU+f0yo0eX4ygH7PzE3PAdlxsCQ==',
    custom: {
        status: 'blocked',
        moment: '2023-11-27T17:21:13.034Z'
    }
}

The proof will be stored but it won't modify the signer status, because this signer is not part of part of circle admin.

GET /v2/signer/bank-admin
 
{
    hash: '...',
    data: {
			handle: 'bank-admin',
			...
		},
		meta: {
		  proofs: [
			  ...,
			  {
				  method: 'ed25519-v2',
				  public: 'FmzUTaV74NRFAd/aILprE=WAweF9PHlboQoW0z8NqhZX',
				  digest: '4969e3c012b66d88cec597bf337fc01eab8d651e6ed2d5c40236cc1f7d93435a',
				  result: '0G2gvSfBx6MwPT8ShBaiYx7zwa5Kqc4Cq3S3NXV1m5/ZPozoH/SUouuhi9sQU+f0yo0eX4ygH7PzE3PAdlxsCQ==',
				  custom: {
				    status: 'blocked',
				    moment: '2023-11-27T17:21:13.034Z'
				  }
				}
			],
		  ...,
		  status: 'active'
		},
		...
}

Then, the signer A, with public WAweF9PHlboQoW0z8NqhZXFmzUTaV74NRFAd/aILprE= , that is part of circle admin , sends a proof to update a bank signer status from active to blocked

POST /v2/signers/bank-admin/proofs
 
{
    method: 'ed25519-v2',
    public: 'WAweF9PHlboQoW0z8NqhZXFmzUTaV74NRFAd/aILprE=',
    digest: '4969e3c012b66d88cec597bf337fc01eab8d651e6ed2d5c40236cc1f7d93435a',
    result: 'BaiYx7zwa5Kqc4Cq3S3N0G2gvSfBx6MwPT8ShXV1m5/ZPozoH/SUouuhi9sQU+f0yo0eX4ygH7PzE3PAdlxsCQ==',
    custom: {
        status: 'blocked',
        moment: '2023-11-27T17:25:14.034Z'
    }
}

The proof will be stored and it will, because quorum required by policy to signer status has fulfilled.

GET /v2/signer/bank-admin
 
{
    hash: '...',
    data: {
			handle: 'bank-admin',
			...
		},
		meta: {
		  proofs: [
			  ...,
			  {
				  method: 'ed25519-v2',
				  public: 'WAweF9PHlboQoW0z8NqhZXFmzUTaV74NRFAd/aILprE=',
				  digest: '4969e3c012b66d88cec597bf337fc01eab8d651e6ed2d5c40236cc1f7d93435a',
				  result: 'BaiYx7zwa5Kqc4Cq3S3N0G2gvSfBx6MwPT8ShXV1m5/ZPozoH/SUouuhi9sQU+f0yo0eX4ygH7PzE3PAdlxsCQ==',
				  custom: {
				    status: 'blocked',
				    moment: '2023-11-27T17:25:14.034Z'
				  }
				}
			],
		  ...,
		  status: 'blocked'
		},
		...
}

Querying by statuses

Statuses can also be useful for querying, ledger allows users to query records by statuses

GET /v2/signers?meta.status=active
 
// Returns an array of all signers that are "active" in ledger

MongoDB Query Language works by doing contains operation on arrays if you pass a single value, see more info here.

Notifying about changed record status

Changing the status of the record fires also <record>-updated event where the new state of record will be delivered to the listener in the record meta of the payload. Also the last proof which caused the change in status will be included in this payload.

For the signer bank-admin above when the blocked status is set, applied the following event payload will be delivered to the listener who registered the effect for signer-update

{
  ...,
  data: {
    signal: 'signer-updated',
    parent: {
      ...,
      data: {
        ...
      },
      meta: {
        status: 'active',
        proofs: [ ... ],
      }
    },
    signer: {
      ...,
      data: {
        ...
      },
      meta: {
        status: 'blocked',
        proofs: [ ..., {
           ...,
           custom: {
             status: 'blocked',
             moment: '2023-11-27T17:25:14.034Z'
           }
        }]
      }
    }
  }
}

On this page