Entities
What Is an Entity?
An entity is the organizational identity layer on ULedgerNET. Where a wallet is a cryptographic keypair, an entity is a named organizational subject (a company, a team, a user account, or an AI agent) that groups wallets under a structured governance hierarchy.
Entities exist to answer the question: "Who does this wallet work for, and what authority does that imply?"
Every wallet that participates in organizational governance must be linked to an entity. An entity defines the wallet's organizational context, controls access to resources, and holds the recovery configuration that survives key loss or leadership changes.
Entity Types
ULedgerNET defines six entity types arranged in a hierarchy:
ORGANIZATION
└── DEPARTMENT
└── PERSONAL
├── SERVICE
├── DEVICE
└── AGENT
| Type | Can Have Children | Typical Use |
|---|---|---|
ORGANIZATION | Yes (any type) | A company, institution, or top-level organizational unit. |
DEPARTMENT | Yes (any type) | A team, division, or sub-unit within an organization. |
PERSONAL | Yes (SERVICE, DEVICE, AGENT only) | A human user's identity. |
SERVICE | No (leaf) | A persistent automated service process. |
DEVICE | No (leaf) | A hardware device or IoT endpoint. |
AGENT | No (leaf) | An autonomous AI agent process. |
Leaf entities (SERVICE, DEVICE, AGENT) cannot have children. They represent the terminal subjects in the hierarchy (the entities that actually perform actions).
PERSONAL entities can only spawn leaf-type children. A human user's identity can own agents, devices, and services, but cannot own sub-organizations or sub-departments.
Entity Data Structure
UL_Entity {
Address string // TransactionId of CREATE_ENTITY tx
Name string // Normalized name (3-64 chars, lowercase, alphanumeric+dash)
EntityType EntityType // ORGANIZATION | DEPARTMENT | PERSONAL | SERVICE | DEVICE | AGENT
Parent string // Parent entity address (empty for top-level)
Owner string // Owner wallet address
Wallets []EntityWalletLink // All linked wallets with roles and permissions
Children []string // Child entity addresses
Enabled bool
Metadata map[string]string // Custom key-value metadata
AccessList AccessList // Blacklist + Trusted list
RecoveryConfig EntityRecoveryConfig
CreatedBlock uint64
}
EntityWalletLink {
WalletAddress string
Role string // "admin" or "member"
Permissions EntityPermission // Fine-grained permission bits (role is stored, not consulted)
}
EntityPermission {
ManageWallets bool
ManageChildren bool
ManageAccessList bool
ManageMetadata bool
TransferOwnership bool
}
The Organizational Hierarchy in Practice
Typical Deployment (Company → Team → User → Agent)
ORGANIZATION: "acme-corp"
│ Owner: corporate-admin-wallet
│
├── DEPARTMENT: "engineering"
│ │ Owner: eng-lead-wallet
│ │
│ └── PERSONAL: "alice"
│ │ Owner: alice-wallet
│ │
│ ├── AGENT: "alice-research-agent"
│ │ Owner: alice-wallet
│ │ Wallet: alice-research-agent-wallet (held by LLM process)
│ │
│ └── SERVICE: "alice-data-pipeline"
│ Owner: alice-wallet
│ Wallet: pipeline-wallet (held by automated service)
│
└── DEPARTMENT: "compliance"
Owner: compliance-lead-wallet
In this structure:
- The
acme-corporganization entity defines the top of the governance tree. - Engineering and compliance are departments with their own governance.
- Alice is a personal entity under engineering.
- Alice's AI research agent is a leaf AGENT entity under Alice.
- The research agent wallet signs its own transactions; its history is permanently attributed to Alice's governance scope.
Permission Model: Bit-Based, Not Role-Based
Critical rule: Authorization on entities is permission-bit based, not role-based.
A wallet linked with role = "member" and Permissions.ManageWallets = true has full wallet management power (the same as an admin). The role field (admin/member) is stored for display and organizational clarity, but it is never consulted during authorization checks.
What matters is which permission bits are set on the EntityWalletLink.
| Permission Bit | What It Allows |
|---|---|
ManageWallets | Link/unlink wallets to/from this entity |
ManageChildren | Create, alter, or remove child entities |
ManageAccessList | Add/remove blacklist and trusted list entries |
ManageMetadata | Update the entity's metadata fields |
TransferOwnership | Transfer the entity to a new owner wallet |
The entity owner wallet always holds all permissions. Additional wallets are linked with whatever subset of permissions the owner grants.
Entity Creation
Entities are created via CREATE_ENTITY transactions.
Creating a Root Entity (No Parent)
{
"name": "acme-corp",
"entityType": "ORGANIZATION",
"metadata": { "description": "Acme Corporation" }
}
Requirements:
- The submitting wallet must be a root wallet (
Parent == ""). - The submitting wallet must not already have an entity affiliation (
wallet.Entity == "").
After creation, the submitting wallet becomes the entity's owner and is linked as an admin-role member with full permissions.
Creating a Child Entity
{
"name": "alice-research-agent",
"entityType": "AGENT",
"parent": "<parent-entity-address>",
"metadata": { "description": "Autonomous research assistant" }
}
Requirements:
- The parent entity must exist and be enabled.
- The parent entity type must support children of the requested type.
- The submitting wallet must have
ManageChildren = trueon the parent entity.
Entity Lifecycle Transactions
| Transaction | Description |
|---|---|
CREATE_ENTITY | Create a new entity. |
ALTER_ENTITY | Update metadata or enable/disable the entity. |
TRANSFER_ENTITY | Change the owner wallet. The new owner's wallet.Entity backlink is updated. |
LINK_WALLET_TO_ENTITY | Add a wallet to the entity with a role and permission bits. |
UNLINK_WALLET_FROM_ENTITY | Remove a wallet from the entity. |
SET_ENTITY_ACCESS_LIST | Add or remove blacklist or trusted-list entries. |
CONFIGURE_ENTITY_RECOVERY | Set recovery wallets and threshold. |
REQUEST_ENTITY_RECOVERY | Initiate a recovery process. |
APPROVE_ENTITY_RECOVERY | Cast an approval vote from a recovery wallet. |
EXECUTE_ENTITY_RECOVERY | Execute recovery after threshold is met. |
CANCEL_ENTITY_RECOVERY | Cancel an in-progress recovery. |
For detailed recovery workflows, threshold selection, and succession scenarios see Recovery.
Entity Ancestry and Authorization
Before any transaction is executed, the entity ancestry chain is validated:
wallet → wallet.Entity → entity.Parent → grandparent.Parent → ...
Every entity in the chain from the wallet's entity up to the root must be enabled. If any ancestor is disabled, all transactions from wallets within that subtree are rejected.
This means:
- Disabling an ORGANIZATION entity disables all wallets in all departments, personal accounts, and agents under it.
- Disabling a PERSONAL entity disables all agent and service wallets owned by that user.
- Disabling an AGENT entity disables only that agent's wallet(s).
The hierarchy enforces organizational control at every level.
Entity Metadata
Entities carry a free-form map[string]string metadata field. There are no reserved keys; the application layer defines the schema.
{
"description": "Research assistant for market analysis",
"pref:budget_monthly": "5000",
"pref:region": "us-east-1",
"compliance:data_classification": "internal"
}
Metadata is mutable (via ALTER_ENTITY) by wallets with ManageMetadata permission. It is stored on-chain and is part of the entity's verifiable record.