Skip to content
    hazBasehazBaseDocs
    IMPLEMENTATION PATTERNS

    Evidence & disclosure

    Combine metadata, credentials and zero-knowledge proofs.

    All implementation patterns
    EXAMPLE

    Connect inspection reports to credentials that recipients can verify

    Store an equipment inspection report and record a pass value plus the report hash in MultiTrustCredential. A recipient can hash the same file and compare it with the recorded value.

    Recipients can check that a report matches its recorded hash and review the issuer, subject and expiry. Inspection accuracy still depends on the inspector and source-data controls.

    Architecture and responsibilities

    1. Inspection and source records

      Manage equipment, inspectors, inspection dates and report versions.

      Inspection system / DB
    2. Document storage and sharing

      Store originals and control access for recipients.

      Storage / Access control
    3. Credential recording

      Record a metric ID, public value, document hash and expiry.

      MultiTrustCredentialHelper
    4. Presentation and verification

      Check the file hash, trusted issuer, expiry and subject.

      Verifier UI / Application policy

    Example data model

    Map application records to the data managed by the chain or APIs. Field names and values below illustrate the application model for this architecture.

    Field and exampleStored inPurpose and mapping
    assetId / subjectWalletROBOT-A-001 / 0x…Application DBMap the credential subject wallet to the asset. The application is responsible for this association.
    documentId / versionINSPECT-001 / v1DB and storageStore reports by version and hash the exact bytes saved and shared, without regenerating them.
    metricId / valueINSPECTION_PASS_V1 / 1ChainHere, 1 is a public inspection-pass value. The issuer defines the metric semantics.
    anchorRootBigInt(documentHash)ChainThis example stores the document’s keccak256 hash. It is a different design from a ZK Merkle root.
    expiresAtUNIX secondsChain and application DBCredential expiry. Define application policies for reinspection and corrections.
    chainId / credentialAddress / transactionHashchain / 0x… / 0x…Application DBIdentify the recorded report using chain, contract and transaction.

    Processing flow

    1. Configure the metric and issuer

      An administrator registers INSPECTION_PASS_V1 and grants its writer role to the issuer. For this public-value example, use commitment false and mask zero because comparisons are not used.

      registerMetric(id, label, writerRole, false, 0) / grantRole
    2. Save and hash the original

      Save the finalized report bytes and compute keccak256 from those exact bytes. Manage signed-URL expiry separately from credential expiry.

      Storage upload → keccak256(reportBytes)
    3. Record the metric for the subject

      Mint value 1, the document hash and expiry for the subject wallet. Minting the same metric for the same wallet updates it, so retain historical reports separately by version and transaction hash.

      MultiTrustCredentialHelper.mint(subjectWallet, input)
    4. Verify the presentation

      The recipient checks the trusted contract and issuer, report hash, metric, subject and expiry. Use MetricUpdated history and current-status information to avoid treating a superseded record as current.

      queryMetricUpdated(fromBlock, toBlock) / application validity checks
    5. Handle corrections and reinspection

      Save the new version, update the metric and retain the link to the previous record. Since historical public data cannot be erased, combine cancellation and supersession indicators with application history.

      updateMetric / document version history

    Before using the code

    • Provide an initialized MultiTrustCredential contract and a signer authorized to write the registered metric.
    • This example treats INSPECTION_PASS_V1 as public. Manage the subject-wallet mapping so another asset does not overwrite the same metric.
    • Pass the finalized original in reportBytes. metadataUri should point to public metadata; protect access to private originals separately.
    Install
    npm install --save-exact @hazbase/kit@0.9.0 ethers@6.16.0

    The TypeScript functions below are called from your application with the appropriate connections, permissions and data. Integrate the UI, persistence and recovery using the architecture above.

    Record the report hash and inspection-pass value

    Pass the report bytes, subject, expiry and issuer to publishInspection. This implements document anchoring; ZK predicate proofs are a separate extension.

    pattern-evidence.ts
    import { MultiTrustCredentialHelper } from '@hazbase/kit';
    import { id, keccak256 } from 'ethers';
    type Signer = Parameters<typeof MultiTrustCredentialHelper.deploy>[1];
    
    const metricId = id('INSPECTION_PASS_V1');
    
    export async function publishInspection(input: {
      credentialAddress: string;
      subjectWallet: string;
      reportBytes: Uint8Array;
      metadataUri: string;
      expiresAt: bigint;
      writer: Signer;
    }) {
      // Register this metric and grant its writer role before calling.
      const credential = MultiTrustCredentialHelper.attach(input.credentialAddress, input.writer);
      const documentHash = keccak256(input.reportBytes);
      const receipt = await credential.mint(input.subjectWallet, {
        metricId,
        value: 1,
        anchorRoot: BigInt(documentHash),
        uri: input.metadataUri,
        expiresAt: input.expiresAt,
      });
    
      // This example anchors document bytes; it does not generate a ZK proof.
      return {
        subject: input.subjectWallet,
        metricId,
        documentHash,
        transactionHash: receipt.hash,
        blockNumber: receipt.blockNumber,
      };
    }
    
    Download the example

    Result and application integration

    Store documentHash and the transaction hash against the report version. anchorRoot corresponds to the on-chain leafFull field. Recipients can hash the same document and compare it with the target transaction record.

    Implementation considerations

    Different bytes produce different hashes

    Regenerating a PDF or changing line endings changes the hash. Verify the original bytes recorded, not a regenerated document.

    Hash integrity versus factual accuracy

    A match establishes correspondence with the document. Verify the inspector, equipment association, expiry and cancellation status separately.

    Disclosure and updates

    Wallets, public values and expiry remain on chain. Model subject and metric boundaries for multiple assets and reports, and separate current values from historical documents.

    Extending the architecture

    Prove a condition without revealing the value

    To prove utilization exceeds a threshold without revealing the value, combine a supported @hazbase/zk circuit, source-data commitment, public inputs and verifier. Storing a document hash alone does not create a ZK proof.

    Connect credentials to eligibility

    A verified result can feed eligibility, for example by registering a qualified user in Whitelist. Align the verifier, root, subject address, expiry and revocation policy.