Document RegistrationDocument Registry

Document Registry

The core contract for document identity and lifecycle management.

Overview

The IntegraDocumentRegistry is the heart of the Integra platform - an immutable smart contract that manages document identity, ownership, and service attachments. Every document registered in Integra receives a unique integraHash identifier that serves as its permanent identity across all chains and services.

Key Features

Immutable Document Identity

Each registered document receives:

struct Document {
    bytes32 integraHash;       // Unique identifier
    bytes32 documentHash;      // Content hash (SHA-256)
    bytes32 referenceHash;     // Storage reference (IPFS CID)
    address owner;             // Document controller
    address tokenizer;         // Associated tokenizer
    address executor;          // Authorized automation agent
    bytes32 processHash;       // Workflow correlation
    bytes32 identityExtension; // Additional identity data
    bytes32 primaryResolverId; // Primary service
    bytes32[] additionalResolverIds; // Additional services
}

Document Registration

function registerDocument(
    bytes32 documentHash,
    bytes32 referenceHash,
    address tokenizer,
    address executor,
    bytes32 processHash,
    bytes32 identityExtension,
    bytes32 primaryResolverId,
    bytes32[] calldata additionalResolverIds
) external returns (bytes32 integraHash);

Parameters:

  • documentHash - SHA-256 hash of document content
  • referenceHash - IPFS CID or storage reference
  • tokenizer - Address of tokenizer contract (or zero for no tokenization)
  • executor - Address authorized for automated operations
  • processHash - Workflow identifier for off-chain correlation
  • identityExtension - Additional identity data
  • primaryResolverId - Primary resolver (must succeed)
  • additionalResolverIds - Additional resolvers (best-effort)

Ownership Management

// Transfer document ownership
function transferOwnership(
    bytes32 integraHash,
    address newOwner,
    string calldata reason
) external;
 
// Query current owner
function getDocumentOwner(bytes32 integraHash)
    external view returns (address);

Resolver Management

// Set primary resolver
function setPrimaryResolver(
    bytes32 integraHash,
    bytes32 resolverId
) external;
 
// Add additional resolver
function addAdditionalResolver(
    bytes32 integraHash,
    bytes32 resolverId
) external;
 
// Lock resolver configuration (permanent)
function lockResolvers(bytes32 integraHash) external;

Registration Flow

1. Prepare document
   ├── Hash document content
   └── Upload to IPFS/storage

2. Call registerDocument()
   ├── Registry validates inputs
   ├── Generates unique integraHash
   ├── Stores document metadata
   ├── Calls resolver hooks
   └── Emits DocumentRegistered event

3. Receive integraHash
   └── Use for all future operations

Events

event DocumentRegistered(
    bytes32 indexed integraHash,
    bytes32 documentHash,
    address indexed owner,
    address tokenizer,
    bytes32 processHash
);
 
event OwnershipTransferred(
    bytes32 indexed integraHash,
    address indexed oldOwner,
    address indexed newOwner,
    string reason
);
 
event ResolverAdded(
    bytes32 indexed integraHash,
    bytes32 resolverId,
    bool isPrimary
);

Code Examples

Basic Registration

import { IntegraDocumentRegistry } from '@integra/sdk';
 
const registry = new IntegraDocumentRegistry(registryAddress, signer);
 
// Hash your document
const documentHash = ethers.utils.sha256(documentContent);
const referenceHash = ipfsCIDToBytes32(cid);
 
// Register
const tx = await registry.registerDocument(
    documentHash,
    referenceHash,
    ownershipTokenizerAddress,
    ethers.constants.AddressZero, // No executor
    ethers.constants.HashZero,    // No process hash
    ethers.constants.HashZero,    // No identity extension
    contactResolverId,            // Primary resolver
    []                            // No additional resolvers
);
 
const receipt = await tx.wait();
const integraHash = receipt.events[0].args.integraHash;

With Resolvers

// Register with multiple resolvers
const tx = await registry.registerDocument(
    documentHash,
    referenceHash,
    rentalTokenizerAddress,
    automationBotAddress,         // Executor for automation
    processHash,                  // Link to CRM workflow
    ethers.constants.HashZero,
    complianceResolverId,         // Primary: compliance checks
    [contactResolverId, lifecycleResolverId] // Additional services
);

Query Document

// Get document details
const doc = await registry.getDocument(integraHash);
console.log('Owner:', doc.owner);
console.log('Tokenizer:', doc.tokenizer);
console.log('Document Hash:', doc.documentHash);
 
// Check if document exists
const exists = await registry.documentExists(integraHash);

Security Considerations

Access Control

  • Only owner can transfer ownership
  • Only owner can modify resolvers
  • Once locked, resolvers cannot be changed
  • Executors have limited permissions

Immutability

  • integraHash never changes
  • documentHash never changes
  • Registration timestamp is permanent
  • Core identity is immutable

Resolver Protection

  • Gas limits prevent DOS attacks
  • Primary resolver failures revert transaction
  • Additional resolver failures are logged but don’t revert

Best Practices

  1. Always verify document hash before registration
  2. Use meaningful processHash for workflow tracking
  3. Consider resolver needs at registration time
  4. Test on testnet before mainnet deployment
  5. Lock resolvers when configuration is final