$ modules/
βββ traceability/ # Food recall domain logic
βββ privacy/ # Selective disclosure ledger
βββ credentialing/ # Hospital staffing clearance
βββ aid-settlement/ # Humanitarian voucher reconciliation
βββ mpc/ # Secret sharing + post-quantum KEM
βββ hsm/ # Envelope encryption + signing
βββ protocols/ # Fabric, Besu, Corda adapters
βββ integrations/ # SDK clients (Gateway, ethers, REST)
modules/
βββ traceability/ # Food recall domain logic
βββ privacy/ # Selective disclosure ledger
βββ credentialing/ # Hospital staffing clearance
βββ aid-settlement/ # Humanitarian voucher reconciliation
βββ mpc/ # Secret sharing + post-quantum KEM
βββ hsm/ # Envelope encryption + signing
βββ protocols/ # Fabric, Besu, Corda adapters
βββ integrations/ # SDK clients (Gateway, ethers, REST)
modules/
βββ traceability/ # Food recall domain logic
βββ privacy/ # Selective disclosure ledger
βββ credentialing/ # Hospital staffing clearance
βββ aid-settlement/ # Humanitarian voucher reconciliation
βββ mpc/ # Secret sharing + post-quantum KEM
βββ hsm/ # Envelope encryption + signing
βββ protocols/ # Fabric, Besu, Corda adapters
βββ integrations/ # SDK clients (Gateway, ethers, REST)
export class TraceabilityLedger { private readonly store: TraceabilityStore; registerLot(lot: ProductLot): void { this.store.addLot(lot); } dispatchShipment(shipment: Shipment): void { this.store.addShipment(shipment); } recordTelemetry(reading: TelemetryReading): void { this.store.addTelemetry(reading); } assessRecall(rule: RecallRule): RecallAssessment { return new RecallAssessor(this.store).assess(rule); }
}
export class TraceabilityLedger { private readonly store: TraceabilityStore; registerLot(lot: ProductLot): void { this.store.addLot(lot); } dispatchShipment(shipment: Shipment): void { this.store.addShipment(shipment); } recordTelemetry(reading: TelemetryReading): void { this.store.addTelemetry(reading); } assessRecall(rule: RecallRule): RecallAssessment { return new RecallAssessor(this.store).assess(rule); }
}
export class TraceabilityLedger { private readonly store: TraceabilityStore; registerLot(lot: ProductLot): void { this.store.addLot(lot); } dispatchShipment(shipment: Shipment): void { this.store.addShipment(shipment); } recordTelemetry(reading: TelemetryReading): void { this.store.addTelemetry(reading); } assessRecall(rule: RecallRule): RecallAssessment { return new RecallAssessor(this.store).assess(rule); }
}
export class FabricTraceabilityAdapter { createLotCommand(lot: ProductLot): FabricInvocation { return { contract: "FoodTraceContract", transaction: "CreateProduct", args: [lot.id, lot.originCountry, lot.supplier, lot.harvestDate], endorsementPolicyHint: "AND('RetailerMSP.peer','SupplierMSP.peer')", }; }
}
export class FabricTraceabilityAdapter { createLotCommand(lot: ProductLot): FabricInvocation { return { contract: "FoodTraceContract", transaction: "CreateProduct", args: [lot.id, lot.originCountry, lot.supplier, lot.harvestDate], endorsementPolicyHint: "AND('RetailerMSP.peer','SupplierMSP.peer')", }; }
}
export class FabricTraceabilityAdapter { createLotCommand(lot: ProductLot): FabricInvocation { return { contract: "FoodTraceContract", transaction: "CreateProduct", args: [lot.id, lot.originCountry, lot.supplier, lot.harvestDate], endorsementPolicyHint: "AND('RetailerMSP.peer','SupplierMSP.peer')", }; }
}
-weight: 500;">npm run example:food-recall
-weight: 500;">npm run example:fabric-projection
-weight: 500;">npm run example:food-recall
-weight: 500;">npm run example:fabric-projection
-weight: 500;">npm run example:food-recall
-weight: 500;">npm run example:fabric-projection
export class SelectiveDisclosureLedger { publishOrder(order: PurchaseOrder): void { this.repo.addOrder(order); } createView(orderId: string, audience: Audience): SharedOrderView { return this.projector.createView(orderId, audience); }
}
export class SelectiveDisclosureLedger { publishOrder(order: PurchaseOrder): void { this.repo.addOrder(order); } createView(orderId: string, audience: Audience): SharedOrderView { return this.projector.createView(orderId, audience); }
}
export class SelectiveDisclosureLedger { publishOrder(order: PurchaseOrder): void { this.repo.addOrder(order); } createView(orderId: string, audience: Audience): SharedOrderView { return this.projector.createView(orderId, audience); }
}
-weight: 500;">npm run example:order-sharing
-weight: 500;">npm run example:besu-projection
-weight: 500;">npm run example:order-sharing
-weight: 500;">npm run example:besu-projection
-weight: 500;">npm run example:order-sharing
-weight: 500;">npm run example:besu-projection
{ flow: "IssueProviderClearanceFlow", participants: ["Hospital-A", "StaffingAgency-X", "LicenseBoard-CA"], state: { providerId: "NP-12345", clearanceStatus: "APPROVED", validUntil: "2026-06-30" }
}
{ flow: "IssueProviderClearanceFlow", participants: ["Hospital-A", "StaffingAgency-X", "LicenseBoard-CA"], state: { providerId: "NP-12345", clearanceStatus: "APPROVED", validUntil: "2026-06-30" }
}
{ flow: "IssueProviderClearanceFlow", participants: ["Hospital-A", "StaffingAgency-X", "LicenseBoard-CA"], state: { providerId: "NP-12345", clearanceStatus: "APPROVED", validUntil: "2026-06-30" }
}
-weight: 500;">npm run example:staffing-clearance
-weight: 500;">npm run example:corda-projection
-weight: 500;">npm run example:staffing-clearance
-weight: 500;">npm run example:corda-projection
-weight: 500;">npm run example:staffing-clearance
-weight: 500;">npm run example:corda-projection
function submitClaim( bytes32 claimId, bytes32 grantId, address merchantId, uint8 merchantCategory, bytes32 invoiceReference, uint256 amountUsd100
) external { Grant storage g = grants[grantId]; require(block.timestamp < g.expiresAt, "Grant expired"); require(g.consumedUsd + amountUsd100 <= g.amountUsd, "Budget exceeded"); require(!usedInvoices[grantId][invoiceReference], "Duplicate invoice"); // ... emit ClaimSettled or ClaimRejected
}
function submitClaim( bytes32 claimId, bytes32 grantId, address merchantId, uint8 merchantCategory, bytes32 invoiceReference, uint256 amountUsd100
) external { Grant storage g = grants[grantId]; require(block.timestamp < g.expiresAt, "Grant expired"); require(g.consumedUsd + amountUsd100 <= g.amountUsd, "Budget exceeded"); require(!usedInvoices[grantId][invoiceReference], "Duplicate invoice"); // ... emit ClaimSettled or ClaimRejected
}
function submitClaim( bytes32 claimId, bytes32 grantId, address merchantId, uint8 merchantCategory, bytes32 invoiceReference, uint256 amountUsd100
) external { Grant storage g = grants[grantId]; require(block.timestamp < g.expiresAt, "Grant expired"); require(g.consumedUsd + amountUsd100 <= g.amountUsd, "Budget exceeded"); require(!usedInvoices[grantId][invoiceReference], "Duplicate invoice"); // ... emit ClaimSettled or ClaimRejected
}
export class MPCEngine { /** * Split `secret` into `partyIds.length` additive shares. * Any strict subset reveals nothing; summing all shares * reconstructs the original value. */ splitSecret(secret: number, partyIds: string[]): SecretShare[] { const shares: SecretShare[] = []; let remaining = secret; for (let i = 0; i < partyIds.length - 1; i++) { const value = randomInt(-(2 ** 47) + 1, 2 ** 47); remaining -= value; const nonce = randomBytes(16).toString("hex"); // Fresh nonce per share shares.push({ partyId: partyIds[i], shareIndex: i, value, nonce, commitment: commitShare(partyIds[i], i, value, nonce), }); } // Last share gets the remainder to ensure sum = original secret return shares; }
}
export class MPCEngine { /** * Split `secret` into `partyIds.length` additive shares. * Any strict subset reveals nothing; summing all shares * reconstructs the original value. */ splitSecret(secret: number, partyIds: string[]): SecretShare[] { const shares: SecretShare[] = []; let remaining = secret; for (let i = 0; i < partyIds.length - 1; i++) { const value = randomInt(-(2 ** 47) + 1, 2 ** 47); remaining -= value; const nonce = randomBytes(16).toString("hex"); // Fresh nonce per share shares.push({ partyId: partyIds[i], shareIndex: i, value, nonce, commitment: commitShare(partyIds[i], i, value, nonce), }); } // Last share gets the remainder to ensure sum = original secret return shares; }
}
export class MPCEngine { /** * Split `secret` into `partyIds.length` additive shares. * Any strict subset reveals nothing; summing all shares * reconstructs the original value. */ splitSecret(secret: number, partyIds: string[]): SecretShare[] { const shares: SecretShare[] = []; let remaining = secret; for (let i = 0; i < partyIds.length - 1; i++) { const value = randomInt(-(2 ** 47) + 1, 2 ** 47); remaining -= value; const nonce = randomBytes(16).toString("hex"); // Fresh nonce per share shares.push({ partyId: partyIds[i], shareIndex: i, value, nonce, commitment: commitShare(partyIds[i], i, value, nonce), }); } // Last share gets the remainder to ensure sum = original secret return shares; }
}
-weight: 500;">npm run example:mpc-auction # Sealed-bid procurement
-weight: 500;">npm run example:mpc-risk-analysis # Cross-institution credit analysis
-weight: 500;">npm run example:mpc-auction # Sealed-bid procurement
-weight: 500;">npm run example:mpc-risk-analysis # Cross-institution credit analysis
-weight: 500;">npm run example:mpc-auction # Sealed-bid procurement
-weight: 500;">npm run example:mpc-risk-analysis # Cross-institution credit analysis
// Distribute a key across 5 custodians, requiring any 3 to reconstruct
const shares = vault.distributeSecret(masterKey, parties, 3);
const reconstructed = vault.reconstructSecret(threeShares, 3);
// Distribute a key across 5 custodians, requiring any 3 to reconstruct
const shares = vault.distributeSecret(masterKey, parties, 3);
const reconstructed = vault.reconstructSecret(threeShares, 3);
// Distribute a key across 5 custodians, requiring any 3 to reconstruct
const shares = vault.distributeSecret(masterKey, parties, 3);
const reconstructed = vault.reconstructSecret(threeShares, 3);
export class HsmClient { generateKeyPair(keyLabel: string): HsmKeyPair; sign(keyLabel: string, data: string): HsmSignatureResult; // Envelope encryption: DEK wrapped by KEK encryptWithEnvelope(kekLabel: string, plaintext: string): { encryptedRecord: EncryptedRecord; wrappedDek: WrappedKey; };
}
export class HsmClient { generateKeyPair(keyLabel: string): HsmKeyPair; sign(keyLabel: string, data: string): HsmSignatureResult; // Envelope encryption: DEK wrapped by KEK encryptWithEnvelope(kekLabel: string, plaintext: string): { encryptedRecord: EncryptedRecord; wrappedDek: WrappedKey; };
}
export class HsmClient { generateKeyPair(keyLabel: string): HsmKeyPair; sign(keyLabel: string, data: string): HsmSignatureResult; // Envelope encryption: DEK wrapped by KEK encryptWithEnvelope(kekLabel: string, plaintext: string): { encryptedRecord: EncryptedRecord; wrappedDek: WrappedKey; };
}
export class HybridKem { /** * Combine X25519 (classical) + ML-KEM-768 (post-quantum). * Breaking this requires breaking BOTH algorithms. */ encapsulate( recipientX25519PublicKey: KeyObject, recipientMlKemPublicKey: Uint8Array, // FIPS 203 naming ): HybridEncapsulation { // Classical channel const x25519SharedSecret = diffieHellman({ /* ... */ }); // Post-quantum channel (ML-KEM-768, formerly "Kyber") const { cipherText, sharedSecret: mlKemSharedSecret } = ml_kem768.encapsulate(recipientMlKemPublicKey); // Combine via HKDF const combinedKey = hkdfSync( "sha256", Buffer.concat([x25519SharedSecret, mlKemSharedSecret]), HKDF_SALT, "hybrid-kem-v1", 32, ); return { combinedKey, /* ... */ }; }
}
export class HybridKem { /** * Combine X25519 (classical) + ML-KEM-768 (post-quantum). * Breaking this requires breaking BOTH algorithms. */ encapsulate( recipientX25519PublicKey: KeyObject, recipientMlKemPublicKey: Uint8Array, // FIPS 203 naming ): HybridEncapsulation { // Classical channel const x25519SharedSecret = diffieHellman({ /* ... */ }); // Post-quantum channel (ML-KEM-768, formerly "Kyber") const { cipherText, sharedSecret: mlKemSharedSecret } = ml_kem768.encapsulate(recipientMlKemPublicKey); // Combine via HKDF const combinedKey = hkdfSync( "sha256", Buffer.concat([x25519SharedSecret, mlKemSharedSecret]), HKDF_SALT, "hybrid-kem-v1", 32, ); return { combinedKey, /* ... */ }; }
}
export class HybridKem { /** * Combine X25519 (classical) + ML-KEM-768 (post-quantum). * Breaking this requires breaking BOTH algorithms. */ encapsulate( recipientX25519PublicKey: KeyObject, recipientMlKemPublicKey: Uint8Array, // FIPS 203 naming ): HybridEncapsulation { // Classical channel const x25519SharedSecret = diffieHellman({ /* ... */ }); // Post-quantum channel (ML-KEM-768, formerly "Kyber") const { cipherText, sharedSecret: mlKemSharedSecret } = ml_kem768.encapsulate(recipientMlKemPublicKey); // Combine via HKDF const combinedKey = hkdfSync( "sha256", Buffer.concat([x25519SharedSecret, mlKemSharedSecret]), HKDF_SALT, "hybrid-kem-v1", 32, ); return { combinedKey, /* ... */ }; }
}
-weight: 500;">npm run example:kyber-kem # Pure ML-KEM-768
-weight: 500;">npm run example:hybrid-kem # X25519 + ML-KEM hybrid
-weight: 500;">npm run example:quantum-safe-payment # End-to-end PQ payment flow
-weight: 500;">npm run example:kyber-kem # Pure ML-KEM-768
-weight: 500;">npm run example:hybrid-kem # X25519 + ML-KEM hybrid
-weight: 500;">npm run example:quantum-safe-payment # End-to-end PQ payment flow
-weight: 500;">npm run example:kyber-kem # Pure ML-KEM-768
-weight: 500;">npm run example:hybrid-kem # X25519 + ML-KEM hybrid
-weight: 500;">npm run example:quantum-safe-payment # End-to-end PQ payment flow
services: besu-validator-1: # Hyperledger Besu node besu-validator-2: fabric-peer: # Hyperledger Fabric peer fabric-orderer: otel-collector: # OpenTelemetry Collector jaeger: # Distributed tracing UI prometheus: # Metrics collection
services: besu-validator-1: # Hyperledger Besu node besu-validator-2: fabric-peer: # Hyperledger Fabric peer fabric-orderer: otel-collector: # OpenTelemetry Collector jaeger: # Distributed tracing UI prometheus: # Metrics collection
services: besu-validator-1: # Hyperledger Besu node besu-validator-2: fabric-peer: # Hyperledger Fabric peer fabric-orderer: otel-collector: # OpenTelemetry Collector jaeger: # Distributed tracing UI prometheus: # Metrics collection
make up # Start everything
make smoke # Run health checks
open http://localhost:16686 # Jaeger traces
open http://localhost:9090 # Prometheus metrics
make up # Start everything
make smoke # Run health checks
open http://localhost:16686 # Jaeger traces
open http://localhost:9090 # Prometheus metrics
make up # Start everything
make smoke # Run health checks
open http://localhost:16686 # Jaeger traces
open http://localhost:9090 # Prometheus metrics
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_SERVICE_NAME=food-recall--weight: 500;">service
-weight: 500;">npm run example:food-recall
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_SERVICE_NAME=food-recall--weight: 500;">service
-weight: 500;">npm run example:food-recall
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_SERVICE_NAME=food-recall--weight: 500;">service
-weight: 500;">npm run example:food-recall
// HSM envelope encryption round-trip
test("envelope encryption: decrypt(encrypt(x)) === x", () => { fc.assert( fc.property( fc.string({ minLength: 1, maxLength: 10000, unit: "binary-ascii" }), (plaintext) => { const { encryptedRecord, wrappedDek } = hsm.encryptWithEnvelope(kekLabel, plaintext); const decrypted = hsm.decryptWithEnvelope(wrappedDek, encryptedRecord); return decrypted === plaintext; }, ), );
});
// HSM envelope encryption round-trip
test("envelope encryption: decrypt(encrypt(x)) === x", () => { fc.assert( fc.property( fc.string({ minLength: 1, maxLength: 10000, unit: "binary-ascii" }), (plaintext) => { const { encryptedRecord, wrappedDek } = hsm.encryptWithEnvelope(kekLabel, plaintext); const decrypted = hsm.decryptWithEnvelope(wrappedDek, encryptedRecord); return decrypted === plaintext; }, ), );
});
// HSM envelope encryption round-trip
test("envelope encryption: decrypt(encrypt(x)) === x", () => { fc.assert( fc.property( fc.string({ minLength: 1, maxLength: 10000, unit: "binary-ascii" }), (plaintext) => { const { encryptedRecord, wrappedDek } = hsm.encryptWithEnvelope(kekLabel, plaintext); const decrypted = hsm.decryptWithEnvelope(wrappedDek, encryptedRecord); return decrypted === plaintext; }, ), );
});
-weight: 500;">npm test # All tests
-weight: 500;">npm test -- tests/hsm.property.test.ts # HSM-specific
-weight: 500;">npm test -- tests/mpc.property.test.ts # MPC-specific
-weight: 500;">npm test # All tests
-weight: 500;">npm test -- tests/hsm.property.test.ts # HSM-specific
-weight: 500;">npm test -- tests/mpc.property.test.ts # MPC-specific
-weight: 500;">npm test # All tests
-weight: 500;">npm test -- tests/hsm.property.test.ts # HSM-specific
-weight: 500;">npm test -- tests/mpc.property.test.ts # MPC-specific
-weight: 500;">git clone --recursive https://github.com/psavelis/enterprise-blockchain.-weight: 500;">git
cd enterprise-blockchain
-weight: 500;">npm -weight: 500;">install
-weight: 500;">npm run verify # format + lint + typecheck + tests + 20 examples
make up # -weight: 500;">start infrastructure (optional)
-weight: 500;">npm run examples # run all business scenarios
-weight: 500;">git clone --recursive https://github.com/psavelis/enterprise-blockchain.-weight: 500;">git
cd enterprise-blockchain
-weight: 500;">npm -weight: 500;">install
-weight: 500;">npm run verify # format + lint + typecheck + tests + 20 examples
make up # -weight: 500;">start infrastructure (optional)
-weight: 500;">npm run examples # run all business scenarios
-weight: 500;">git clone --recursive https://github.com/psavelis/enterprise-blockchain.-weight: 500;">git
cd enterprise-blockchain
-weight: 500;">npm -weight: 500;">install
-weight: 500;">npm run verify # format + lint + typecheck + tests + 20 examples
make up # -weight: 500;">start infrastructure (optional)
-weight: 500;">npm run examples # run all business scenarios
-weight: 500;">npm run verify # format:check + lint + typecheck + test + all examples
-weight: 500;">npm run verify # format:check + lint + typecheck + test + all examples
-weight: 500;">npm run verify # format:check + lint + typecheck + test + all examples - 4 production case studies with domain models and real code
- 3 protocol adapters (Hyperledger Fabric, Besu/EVM, R3 Corda)
- Post-quantum cryptography (NIST FIPS 203/204 compliant)
- MPC and HSM patterns for off-chain computation and key custody
- Full local infrastructure (Docker Compose + OpenTelemetry + Jaeger)
- AI skill files that teach coding assistants the domain - Domain layer: Pure business logic. No protocol dependencies. Fully unit-testable.
- Protocol adapters: Stateless projectors that translate domain events into platform-specific transaction shapes.
- Integration clients: SDK wrappers with retry policies, circuit breakers, and connection management. - hsm-transaction-signing: ECDSA-SHA256 for equity trade orders
- hsm-key-ceremony: Root key ceremony with 3-of-5 Shamir threshold
- hsm-envelope-encryption: DEK/KEK for sensitive trade documents - Resource limits (CPU/memory) on all containers
- no-new-privileges: true blocks privilege escalation
- Log rotation prevents disk exhaustion
- All ports bound to 127.0.0.1 - Off-by-one errors in field arithmetic
- IV reuse across encryptions
- Implicit rejection failures in post-quantum KEMs - Platform selection follows trust, not throughput. Feature matrices are noise. Teams pick Fabric because they have Java developers. They pick Besu because they know EVM. They pick Corda because R3 has regulatory relationships. Throughput differences matter only after trust assumptions narrow the field.
- Privacy is architecture, not configuration. Every platform offers privacy mechanisms. None of them work without deliberate design. If your public contract queries private state, you've leaked data.
- Off-chain is not optional. Every production deployment stores bulk data off-chain. The blockchain stores commitments, not content. Plan for this from day one.
- Integration complexity dominates. Chaincode development is 20-30% of the project. Identity integration, legacy system bridges, and operational tooling consume the rest.
- Governance evolves faster than code. Consortium agreements written at kickoff become obsolete. New members require endorsement policy changes. Regulatory requirements mandate audit observer nodes. Design for governance evolution from day one.
- Consensus selection follows trust, not throughput. Marketing materials emphasize throughput differences. Production deployments choose based on trust assumptions. Raft (CFT) for aligned incentives. QBFT (BFT) for competing parties. The throughput numbers are noise. - Blockchain architects evaluating Fabric vs Besu vs Corda
- Security engineers implementing MPC, HSM, or post-quantum patterns
- Protocol researchers studying transaction shape mappings
- Teams in PoC purgatory who need production-grade examples
- Anyone who's tired of blockchain demos that don't actually run
- Developers learning enterprise blockchain who want working examples, not slides - Study Guide β Recommended reading order for architects
- Architecture Guides β Platform decision matrix, protocol flows, observability
- Research Notes β Industry deployments and lessons learned
- AI Skills β Structured knowledge files for coding assistants