Minka Ledger Docs
Explanations

About Domains

DateResponsibleChanges
November 14, 2024@Omar MonterreyInitial version

What is a domain

Domains are namespaces inside ledger, allowing to group all other ledger records and inherit access rules inside this scoped namespace.

Domains exist as a record and are optional. If no domain exists the users can assign ledger records to any domain, but once the first domain is created, ledger starts enforcing domains rules. This means that the domain being assigned should exist as a record and the user should have access to create records inside that domain.

Defining domains creates restrictions that apply only to records created after it’s definition. Any record created while domains were not defined will still be valid and won’t be automatically migrated.

The root domain

When a record does not belong to any specific domain, we say that it belongs to the “root” domain. When querying the domain of a record that is in the root domain, it will be undefined, this is the default behavior of the ledger.

Domain-Record assignation

Currently domain of a record can only be assigned during creation and can’t be updated later. There are two methods for defining the domain of a record:

Implicit assignation (With handle)

When creating a record, a domain can be assigned by appending @<domain> at the end of the handle. For example, creating a wallet with handle treasury will assign it to root domain, but creating a wallet with handle treasury@minka.io will assign the wallet to the domain minka.io

Explicit assignation (With proof)

Domain can also be explicitly assigned by sending the domain property as part of the proof’s custom data when signing the record. And example using ledger SDK would be:

sdk.wallet
    .init()
    .data({
        handle: 'treasury', // No domain is required in the handle
        access: [...],
    })
    .hash()
    .sign([
        {
            keyPair: signerKeyPair,
            custom: {
                domain: 'minka.io',
            }
        }
    ])

Handle uniqueness still applies for different domains inside the same ledger. This means that wallet “treasury” can’t exist with the same handle in different domains. This includes root domain.

Explicit assignation have preference over implicit assignation, that means if the record’s handle is domain-a but creation is signed with domain: domain-b then the record will be created inside domain-b

Records that can be assigned to a domain

  • Anchors
  • Bridges
  • Circles
  • Domains (To create sub domains)
  • Effects
  • Intents
  • Policies
  • Reports
  • Schemas
  • Signers
  • Symbols
  • Wallets

Querying a record’s domain

The domain of a record is available as part of it’s metadata, this means you can query it from the meta property of the response when reading it.

const { meta } = await sdk.wallet.read('<handle>')
const domain = meta.domain

Metadata can’t be modified in update operations

Domain security

When trying to perform write or read operations against a record, the security rules of it’s domain are checked. Access rules are inherited from the root to the domains and subdomains below it. This means that any access rules that grant access to perform an operation in the top level, will also allow you to perform this same operation in a lower level.

  • Inheritance diagram

  • Sample scenario

    Given the scenario where we have access rules at top level that allows signer admin to perform any operation, then in the domain domainA we have access rules that allow the signer admin@domainA to perform any operation and in the domain domainC we have access rules that allow the signer admin@domainC to perform any operation, this is a comparison table of resulting permissions:

    Permission/Useradminadmin@domainAadmin@domainC
    Operations at root level (Ledger)🟢🔴🔴
    Operations at domainA level🟢🟢🔴
    Operations at domainC level🟢🟢🟢

Define domain access rules

Defining access rules for the domain is similar to defining the access rules for the ledger. In this case, the access rules or policies should be set in the access property of the domain record.

For example, to allow the signer with the public key my-public-key to perform any operation inside the domain, you can define the access rules like this (Example using ledger SDK):

sdk.domain
    .init()
    .data({
        handle: 'minka.io',
        access: [
            {
                action: AccessAction.Any,
                record: AccessRecord.Any,
                signer: {
                    public: 'my-public-key',
                }
            }
        ], 
    })

On this page