@psavelis/enterprise-blockchain 0.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -2
- package/dist/aid-settlement/application/reconciler.d.ts +13 -0
- package/dist/aid-settlement/application/reconciler.d.ts.map +1 -0
- package/dist/aid-settlement/application/reconciler.js +77 -0
- package/dist/aid-settlement/domain/entities.d.ts +24 -0
- package/dist/aid-settlement/domain/entities.d.ts.map +1 -0
- package/dist/aid-settlement/domain/entities.js +1 -0
- package/dist/aid-settlement/domain/ports.d.ts +10 -0
- package/dist/aid-settlement/domain/ports.d.ts.map +1 -0
- package/dist/aid-settlement/domain/ports.js +1 -0
- package/dist/aid-settlement/index.d.ts +19 -0
- package/dist/aid-settlement/index.d.ts.map +1 -0
- package/dist/aid-settlement/index.js +23 -0
- package/dist/aid-settlement/infrastructure/in-memory-store.d.ts +12 -0
- package/dist/aid-settlement/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/aid-settlement/infrastructure/in-memory-store.js +17 -0
- package/dist/credentialing/application/clearance-evaluator.d.ts +10 -0
- package/dist/credentialing/application/clearance-evaluator.d.ts.map +1 -0
- package/dist/credentialing/application/clearance-evaluator.js +63 -0
- package/dist/credentialing/domain/entities.d.ts +28 -0
- package/dist/credentialing/domain/entities.d.ts.map +1 -0
- package/dist/credentialing/domain/entities.js +1 -0
- package/dist/credentialing/domain/ports.d.ts +9 -0
- package/dist/credentialing/domain/ports.d.ts.map +1 -0
- package/dist/credentialing/domain/ports.js +1 -0
- package/dist/credentialing/index.d.ts +19 -0
- package/dist/credentialing/index.d.ts.map +1 -0
- package/dist/credentialing/index.js +23 -0
- package/dist/credentialing/infrastructure/in-memory-store.d.ts +11 -0
- package/dist/credentialing/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/credentialing/infrastructure/in-memory-store.js +14 -0
- package/dist/hsm/application/asymmetric-key-service.d.ts +23 -0
- package/dist/hsm/application/asymmetric-key-service.d.ts.map +1 -0
- package/dist/hsm/application/asymmetric-key-service.js +109 -0
- package/dist/hsm/application/envelope-encryption-service.d.ts +18 -0
- package/dist/hsm/application/envelope-encryption-service.d.ts.map +1 -0
- package/dist/hsm/application/envelope-encryption-service.js +59 -0
- package/dist/hsm/application/symmetric-key-service.d.ts +34 -0
- package/dist/hsm/application/symmetric-key-service.d.ts.map +1 -0
- package/dist/hsm/application/symmetric-key-service.js +107 -0
- package/dist/hsm/domain/entities.d.ts +104 -0
- package/dist/hsm/domain/entities.d.ts.map +1 -0
- package/dist/hsm/domain/entities.js +10 -0
- package/dist/hsm/domain/ports.d.ts +20 -0
- package/dist/hsm/domain/ports.d.ts.map +1 -0
- package/dist/hsm/domain/ports.js +1 -0
- package/dist/hsm/index.d.ts +48 -0
- package/dist/hsm/index.d.ts.map +1 -0
- package/dist/hsm/index.js +97 -0
- package/dist/hsm/infrastructure/audit-log-factory.d.ts +59 -0
- package/dist/hsm/infrastructure/audit-log-factory.d.ts.map +1 -0
- package/dist/hsm/infrastructure/audit-log-factory.js +95 -0
- package/dist/hsm/infrastructure/audit-log.d.ts +8 -0
- package/dist/hsm/infrastructure/audit-log.d.ts.map +1 -0
- package/dist/hsm/infrastructure/audit-log.js +18 -0
- package/dist/hsm/infrastructure/file-audit-log.d.ts +55 -0
- package/dist/hsm/infrastructure/file-audit-log.d.ts.map +1 -0
- package/dist/hsm/infrastructure/file-audit-log.js +128 -0
- package/dist/hsm/infrastructure/key-store.d.ts +9 -0
- package/dist/hsm/infrastructure/key-store.d.ts.map +1 -0
- package/dist/hsm/infrastructure/key-store.js +12 -0
- package/dist/hsm/infrastructure/syslog-audit-log.d.ts +64 -0
- package/dist/hsm/infrastructure/syslog-audit-log.d.ts.map +1 -0
- package/dist/hsm/infrastructure/syslog-audit-log.js +167 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/integrations/besu-client/error-mapper.d.ts +9 -0
- package/dist/integrations/besu-client/error-mapper.d.ts.map +1 -0
- package/dist/integrations/besu-client/error-mapper.js +22 -0
- package/dist/integrations/besu-client/index.d.ts +65 -0
- package/dist/integrations/besu-client/index.d.ts.map +1 -0
- package/dist/integrations/besu-client/index.js +276 -0
- package/dist/integrations/besu-client/ports.d.ts +44 -0
- package/dist/integrations/besu-client/ports.d.ts.map +1 -0
- package/dist/integrations/besu-client/ports.js +1 -0
- package/dist/integrations/corda-gateway/index.d.ts +37 -0
- package/dist/integrations/corda-gateway/index.d.ts.map +1 -0
- package/dist/integrations/corda-gateway/index.js +234 -0
- package/dist/integrations/corda-gateway/ports.d.ts +33 -0
- package/dist/integrations/corda-gateway/ports.d.ts.map +1 -0
- package/dist/integrations/corda-gateway/ports.js +1 -0
- package/dist/integrations/fabric-gateway/index.d.ts +78 -0
- package/dist/integrations/fabric-gateway/index.d.ts.map +1 -0
- package/dist/integrations/fabric-gateway/index.js +214 -0
- package/dist/integrations/fabric-gateway/ports.d.ts +50 -0
- package/dist/integrations/fabric-gateway/ports.d.ts.map +1 -0
- package/dist/integrations/fabric-gateway/ports.js +1 -0
- package/dist/integrations/index.d.ts +19 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +19 -0
- package/dist/integrations/shared/env.d.ts +4 -0
- package/dist/integrations/shared/env.d.ts.map +1 -0
- package/dist/integrations/shared/env.js +24 -0
- package/dist/integrations/shared/retry.d.ts +79 -0
- package/dist/integrations/shared/retry.d.ts.map +1 -0
- package/dist/integrations/shared/retry.js +315 -0
- package/dist/mpc/adapters.d.ts +36 -0
- package/dist/mpc/adapters.d.ts.map +1 -0
- package/dist/mpc/adapters.js +46 -0
- package/dist/mpc/crypto.d.ts +2 -0
- package/dist/mpc/crypto.d.ts.map +1 -0
- package/dist/mpc/crypto.js +2 -0
- package/dist/mpc/dsa.d.ts +134 -0
- package/dist/mpc/dsa.d.ts.map +1 -0
- package/dist/mpc/dsa.js +127 -0
- package/dist/mpc/field.d.ts +127 -0
- package/dist/mpc/field.d.ts.map +1 -0
- package/dist/mpc/field.js +209 -0
- package/dist/mpc/hybrid-kem.d.ts +96 -0
- package/dist/mpc/hybrid-kem.d.ts.map +1 -0
- package/dist/mpc/hybrid-kem.js +136 -0
- package/dist/mpc/index.d.ts +135 -0
- package/dist/mpc/index.d.ts.map +1 -0
- package/dist/mpc/index.js +348 -0
- package/dist/mpc/kyber.d.ts +134 -0
- package/dist/mpc/kyber.d.ts.map +1 -0
- package/dist/mpc/kyber.js +143 -0
- package/dist/mpc/ports.d.ts +67 -0
- package/dist/mpc/ports.d.ts.map +1 -0
- package/dist/mpc/ports.js +9 -0
- package/dist/mpc/quantum.d.ts +80 -0
- package/dist/mpc/quantum.d.ts.map +1 -0
- package/dist/mpc/quantum.js +180 -0
- package/dist/p2mr/adapters.d.ts +31 -0
- package/dist/p2mr/adapters.d.ts.map +1 -0
- package/dist/p2mr/adapters.js +35 -0
- package/dist/p2mr/index.d.ts +63 -0
- package/dist/p2mr/index.d.ts.map +1 -0
- package/dist/p2mr/index.js +59 -0
- package/dist/p2mr/merkle-tree.d.ts +109 -0
- package/dist/p2mr/merkle-tree.d.ts.map +1 -0
- package/dist/p2mr/merkle-tree.js +239 -0
- package/dist/p2mr/p2mr-output.d.ts +142 -0
- package/dist/p2mr/p2mr-output.d.ts.map +1 -0
- package/dist/p2mr/p2mr-output.js +150 -0
- package/dist/p2mr/ports.d.ts +52 -0
- package/dist/p2mr/ports.d.ts.map +1 -0
- package/dist/p2mr/ports.js +9 -0
- package/dist/p2mr/script-interpreter.d.ts +92 -0
- package/dist/p2mr/script-interpreter.d.ts.map +1 -0
- package/dist/p2mr/script-interpreter.js +535 -0
- package/dist/p2mr/script-leaf.d.ts +70 -0
- package/dist/p2mr/script-leaf.d.ts.map +1 -0
- package/dist/p2mr/script-leaf.js +203 -0
- package/dist/p2mr/spend-proof.d.ts +95 -0
- package/dist/p2mr/spend-proof.d.ts.map +1 -0
- package/dist/p2mr/spend-proof.js +358 -0
- package/dist/p2mr/types.d.ts +209 -0
- package/dist/p2mr/types.d.ts.map +1 -0
- package/dist/p2mr/types.js +9 -0
- package/dist/privacy/application/view-projector.d.ts +13 -0
- package/dist/privacy/application/view-projector.d.ts.map +1 -0
- package/dist/privacy/application/view-projector.js +85 -0
- package/dist/privacy/domain/entities.d.ts +26 -0
- package/dist/privacy/domain/entities.d.ts.map +1 -0
- package/dist/privacy/domain/entities.js +1 -0
- package/dist/privacy/domain/ports.d.ts +7 -0
- package/dist/privacy/domain/ports.d.ts.map +1 -0
- package/dist/privacy/domain/ports.js +1 -0
- package/dist/privacy/index.d.ts +21 -0
- package/dist/privacy/index.d.ts.map +1 -0
- package/dist/privacy/index.js +25 -0
- package/dist/privacy/infrastructure/in-memory-store.d.ts +8 -0
- package/dist/privacy/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/privacy/infrastructure/in-memory-store.js +7 -0
- package/dist/protocols/besu-port.d.ts +80 -0
- package/dist/protocols/besu-port.d.ts.map +1 -0
- package/dist/protocols/besu-port.js +1 -0
- package/dist/protocols/corda-port.d.ts +103 -0
- package/dist/protocols/corda-port.d.ts.map +1 -0
- package/dist/protocols/corda-port.js +9 -0
- package/dist/protocols/credentialing-port.d.ts +11 -0
- package/dist/protocols/credentialing-port.d.ts.map +1 -0
- package/dist/protocols/credentialing-port.js +1 -0
- package/dist/protocols/fabric-port.d.ts +89 -0
- package/dist/protocols/fabric-port.d.ts.map +1 -0
- package/dist/protocols/fabric-port.js +9 -0
- package/dist/protocols/index.d.ts +14 -0
- package/dist/protocols/index.d.ts.map +1 -0
- package/dist/protocols/index.js +7 -0
- package/dist/protocols/p2mr-port.d.ts +159 -0
- package/dist/protocols/p2mr-port.d.ts.map +1 -0
- package/dist/protocols/p2mr-port.js +12 -0
- package/dist/protocols/privacy-port.d.ts +9 -0
- package/dist/protocols/privacy-port.d.ts.map +1 -0
- package/dist/protocols/privacy-port.js +1 -0
- package/dist/protocols/traceability-port.d.ts +12 -0
- package/dist/protocols/traceability-port.d.ts.map +1 -0
- package/dist/protocols/traceability-port.js +1 -0
- package/dist/shared/collection-store.d.ts +12 -0
- package/dist/shared/collection-store.d.ts.map +1 -0
- package/dist/shared/collection-store.js +26 -0
- package/dist/shared/commit.d.ts +24 -0
- package/dist/shared/commit.d.ts.map +1 -0
- package/dist/shared/commit.js +50 -0
- package/dist/shared/crypto.d.ts +2 -0
- package/dist/shared/crypto.d.ts.map +1 -0
- package/dist/shared/crypto.js +4 -0
- package/dist/shared/date.d.ts +2 -0
- package/dist/shared/date.d.ts.map +1 -0
- package/dist/shared/date.js +3 -0
- package/dist/shared/index.d.ts +9 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +11 -0
- package/dist/shared/logger.d.ts +37 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +45 -0
- package/dist/shared/store.d.ts +25 -0
- package/dist/shared/store.d.ts.map +1 -0
- package/dist/shared/store.js +18 -0
- package/dist/shared/telemetry-sdk.d.ts +26 -0
- package/dist/shared/telemetry-sdk.d.ts.map +1 -0
- package/dist/shared/telemetry-sdk.js +97 -0
- package/dist/shared/telemetry.d.ts +86 -0
- package/dist/shared/telemetry.d.ts.map +1 -0
- package/dist/shared/telemetry.js +137 -0
- package/dist/stark-settlement/application/aggregator-service.d.ts +112 -0
- package/dist/stark-settlement/application/aggregator-service.d.ts.map +1 -0
- package/dist/stark-settlement/application/aggregator-service.js +256 -0
- package/dist/stark-settlement/application/ledger-service.d.ts +114 -0
- package/dist/stark-settlement/application/ledger-service.d.ts.map +1 -0
- package/dist/stark-settlement/application/ledger-service.js +318 -0
- package/dist/stark-settlement/application/settlement-service.d.ts +104 -0
- package/dist/stark-settlement/application/settlement-service.d.ts.map +1 -0
- package/dist/stark-settlement/application/settlement-service.js +251 -0
- package/dist/stark-settlement/domain/entities.d.ts +365 -0
- package/dist/stark-settlement/domain/entities.d.ts.map +1 -0
- package/dist/stark-settlement/domain/entities.js +29 -0
- package/dist/stark-settlement/domain/ports.d.ts +485 -0
- package/dist/stark-settlement/domain/ports.d.ts.map +1 -0
- package/dist/stark-settlement/domain/ports.js +14 -0
- package/dist/stark-settlement/domain/value-objects.d.ts +268 -0
- package/dist/stark-settlement/domain/value-objects.d.ts.map +1 -0
- package/dist/stark-settlement/domain/value-objects.js +500 -0
- package/dist/stark-settlement/index.d.ts +172 -0
- package/dist/stark-settlement/index.d.ts.map +1 -0
- package/dist/stark-settlement/index.js +193 -0
- package/dist/stark-settlement/infrastructure/adapters/audit-adapter.d.ts +52 -0
- package/dist/stark-settlement/infrastructure/adapters/audit-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/audit-adapter.js +154 -0
- package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.d.ts +88 -0
- package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.js +187 -0
- package/dist/stark-settlement/infrastructure/adapters/clock-adapter.d.ts +59 -0
- package/dist/stark-settlement/infrastructure/adapters/clock-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/clock-adapter.js +85 -0
- package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.d.ts +60 -0
- package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.js +104 -0
- package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.d.ts +115 -0
- package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.js +191 -0
- package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.d.ts +65 -0
- package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.js +207 -0
- package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.d.ts +73 -0
- package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.js +287 -0
- package/dist/stark-settlement/infrastructure/adapters/solana-adapter.d.ts +78 -0
- package/dist/stark-settlement/infrastructure/adapters/solana-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/solana-adapter.js +172 -0
- package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.d.ts +56 -0
- package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.js +261 -0
- package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.d.ts +125 -0
- package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.js +416 -0
- package/dist/stark-settlement/infrastructure/persistence/ledger-store.d.ts +68 -0
- package/dist/stark-settlement/infrastructure/persistence/ledger-store.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/persistence/ledger-store.js +238 -0
- package/dist/stark-settlement/infrastructure/persistence/offset-store.d.ts +30 -0
- package/dist/stark-settlement/infrastructure/persistence/offset-store.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/persistence/offset-store.js +57 -0
- package/dist/stark-settlement/infrastructure/persistence/outbox-store.d.ts +45 -0
- package/dist/stark-settlement/infrastructure/persistence/outbox-store.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/persistence/outbox-store.js +171 -0
- package/dist/traceability/application/recall-assessor.d.ts +13 -0
- package/dist/traceability/application/recall-assessor.d.ts.map +1 -0
- package/dist/traceability/application/recall-assessor.js +74 -0
- package/dist/traceability/domain/entities.d.ts +23 -0
- package/dist/traceability/domain/entities.d.ts.map +1 -0
- package/dist/traceability/domain/entities.js +1 -0
- package/dist/traceability/domain/ports.d.ts +23 -0
- package/dist/traceability/domain/ports.d.ts.map +1 -0
- package/dist/traceability/domain/ports.js +1 -0
- package/dist/traceability/domain/recall.d.ts +12 -0
- package/dist/traceability/domain/recall.d.ts.map +1 -0
- package/dist/traceability/domain/recall.js +1 -0
- package/dist/traceability/index.d.ts +22 -0
- package/dist/traceability/index.d.ts.map +1 -0
- package/dist/traceability/index.js +26 -0
- package/dist/traceability/infrastructure/in-memory-store.d.ts +13 -0
- package/dist/traceability/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/traceability/infrastructure/in-memory-store.js +24 -0
- package/package.json +12 -9
package/README.md
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
# @psavelis/enterprise-blockchain
|
|
2
2
|
|
|
3
|
-
Production-grade
|
|
3
|
+
Production-grade TypeScript modules for recursive STARK settlement, post-quantum cryptography (ML-KEM/ML-DSA), MPC, HSM, and multi-rail (Solana + Bitcoin + fiat) infrastructure.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@psavelis/enterprise-blockchain)
|
|
6
6
|
[](../../LICENSE)
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Install in 10 Seconds
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
11
|
npm install @psavelis/enterprise-blockchain
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
+
```typescript
|
|
15
|
+
import { KyberKem } from "@psavelis/enterprise-blockchain/mpc";
|
|
16
|
+
|
|
17
|
+
// Post-quantum key exchange (NIST FIPS 203)
|
|
18
|
+
const kem = new KyberKem();
|
|
19
|
+
const { publicKey, secretKey } = kem.generateKeyPair("ml-kem-768");
|
|
20
|
+
const { ciphertext, sharedSecret } = kem.encapsulate(publicKey, "ml-kem-768");
|
|
21
|
+
const decrypted = kem.decapsulate(ciphertext, secretKey, "ml-kem-768");
|
|
22
|
+
// sharedSecret === decrypted ✓
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
14
27
|
## Quick Start
|
|
15
28
|
|
|
16
29
|
### Post-Quantum Key Exchange (ML-KEM-768)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReconciliationReport } from "../domain/entities.js";
|
|
2
|
+
import type { AidSettlementRepository } from "../domain/ports.js";
|
|
3
|
+
import type { Logger } from "../../shared/logger.js";
|
|
4
|
+
export declare class Reconciler {
|
|
5
|
+
private readonly repo;
|
|
6
|
+
private readonly logger;
|
|
7
|
+
constructor(repo: AidSettlementRepository, logger?: Logger);
|
|
8
|
+
reconcile(): ReconciliationReport;
|
|
9
|
+
private rejectOrphanedClaims;
|
|
10
|
+
private processClaims;
|
|
11
|
+
private validateClaim;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=reconciler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconciler.d.ts","sourceRoot":"","sources":["../../../src/aid-settlement/application/reconciler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,oBAAoB,EACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGrD,qBAAa,UAAU;IAInB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAGb,IAAI,EAAE,uBAAuB,EAC9C,MAAM,CAAC,EAAE,MAAM;IAKjB,SAAS,IAAI,oBAAoB;IAiDjC,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,aAAa;IA8BrB,OAAO,CAAC,aAAa;CA6BtB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { noopLogger } from "../../shared/logger.js";
|
|
2
|
+
export class Reconciler {
|
|
3
|
+
repo;
|
|
4
|
+
logger;
|
|
5
|
+
constructor(repo, logger) {
|
|
6
|
+
this.repo = repo;
|
|
7
|
+
this.logger = logger ?? noopLogger;
|
|
8
|
+
}
|
|
9
|
+
reconcile() {
|
|
10
|
+
const start = Date.now();
|
|
11
|
+
this.logger.info("reconciliation started", {
|
|
12
|
+
operation: "Reconciler.reconcile",
|
|
13
|
+
});
|
|
14
|
+
const settledClaimIds = [];
|
|
15
|
+
const rejectedClaimIds = [];
|
|
16
|
+
const exceptions = [];
|
|
17
|
+
for (const grantId of this.repo.grantIds()) {
|
|
18
|
+
const grant = this.repo.grants.get(grantId);
|
|
19
|
+
const claims = this.repo.claimsForGrant(grantId);
|
|
20
|
+
if (!grant) {
|
|
21
|
+
this.rejectOrphanedClaims(claims, grantId, rejectedClaimIds, exceptions);
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
this.processClaims(grant, claims, settledClaimIds, rejectedClaimIds, exceptions);
|
|
25
|
+
}
|
|
26
|
+
const report = {
|
|
27
|
+
settledClaimIds,
|
|
28
|
+
rejectedClaimIds,
|
|
29
|
+
exceptions,
|
|
30
|
+
};
|
|
31
|
+
this.logger.info("reconciliation completed", {
|
|
32
|
+
operation: "Reconciler.reconcile",
|
|
33
|
+
result: exceptions.length > 0 ? "with-exceptions" : "clean",
|
|
34
|
+
durationMs: Date.now() - start,
|
|
35
|
+
settled: settledClaimIds.length,
|
|
36
|
+
rejected: rejectedClaimIds.length,
|
|
37
|
+
});
|
|
38
|
+
return report;
|
|
39
|
+
}
|
|
40
|
+
rejectOrphanedClaims(claims, grantId, rejectedClaimIds, exceptions) {
|
|
41
|
+
for (const claim of claims) {
|
|
42
|
+
rejectedClaimIds.push(claim.id);
|
|
43
|
+
}
|
|
44
|
+
exceptions.push(`Claims reference unknown grant ${grantId}.`);
|
|
45
|
+
}
|
|
46
|
+
processClaims(grant, claims, settledClaimIds, rejectedClaimIds, exceptions) {
|
|
47
|
+
let consumedAmountUsd = 0;
|
|
48
|
+
const seenInvoices = new Set();
|
|
49
|
+
for (const claim of claims) {
|
|
50
|
+
const rejection = this.validateClaim(claim, grant, consumedAmountUsd, seenInvoices);
|
|
51
|
+
if (rejection) {
|
|
52
|
+
rejectedClaimIds.push(claim.id);
|
|
53
|
+
exceptions.push(...rejection);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
consumedAmountUsd += claim.amountUsd;
|
|
57
|
+
seenInvoices.add(claim.invoiceReference);
|
|
58
|
+
settledClaimIds.push(claim.id);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
validateClaim(claim, grant, consumedAmountUsd, seenInvoices) {
|
|
62
|
+
const errors = [];
|
|
63
|
+
if (new Date(claim.submittedAt) > new Date(grant.expiresAt)) {
|
|
64
|
+
errors.push(`Claim ${claim.id} was submitted after grant ${grant.id} expired.`);
|
|
65
|
+
}
|
|
66
|
+
if (!grant.approvedMerchantCategories.includes(claim.merchantCategory)) {
|
|
67
|
+
errors.push(`Claim ${claim.id} used merchant category ${claim.merchantCategory}, which is not approved.`);
|
|
68
|
+
}
|
|
69
|
+
if (seenInvoices.has(claim.invoiceReference)) {
|
|
70
|
+
errors.push(`Claim ${claim.id} duplicated invoice ${claim.invoiceReference}.`);
|
|
71
|
+
}
|
|
72
|
+
if (consumedAmountUsd + claim.amountUsd > grant.amountUsd) {
|
|
73
|
+
errors.push(`Claim ${claim.id} would overspend grant ${grant.id}.`);
|
|
74
|
+
}
|
|
75
|
+
return errors.length > 0 ? errors : null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface AidGrant {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly beneficiaryId: string;
|
|
4
|
+
readonly program: string;
|
|
5
|
+
readonly issuedAt: string;
|
|
6
|
+
readonly expiresAt: string;
|
|
7
|
+
readonly approvedMerchantCategories: string[];
|
|
8
|
+
readonly amountUsd: number;
|
|
9
|
+
}
|
|
10
|
+
export interface RedemptionClaim {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly grantId: string;
|
|
13
|
+
readonly merchantId: string;
|
|
14
|
+
readonly merchantCategory: string;
|
|
15
|
+
readonly submittedAt: string;
|
|
16
|
+
readonly invoiceReference: string;
|
|
17
|
+
readonly amountUsd: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ReconciliationReport {
|
|
20
|
+
readonly settledClaimIds: string[];
|
|
21
|
+
readonly rejectedClaimIds: string[];
|
|
22
|
+
readonly exceptions: string[];
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=entities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../../src/aid-settlement/domain/entities.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,0BAA0B,EAAE,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;CAC/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReadonlyStore } from "../../shared/store.js";
|
|
2
|
+
import type { AidGrant, RedemptionClaim } from "./entities.js";
|
|
3
|
+
export interface AidSettlementRepository {
|
|
4
|
+
readonly grants: ReadonlyStore<string, AidGrant>;
|
|
5
|
+
claimsForGrant(grantId: string): readonly RedemptionClaim[];
|
|
6
|
+
grantIds(): Iterable<string>;
|
|
7
|
+
addGrant(grant: AidGrant): void;
|
|
8
|
+
addClaim(claim: RedemptionClaim): void;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=ports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../src/aid-settlement/domain/ports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE/D,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACjD,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,eAAe,EAAE,CAAC;IAC5D,QAAQ,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;CACxC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type { AidGrant, RedemptionClaim, ReconciliationReport, } from "./domain/entities.js";
|
|
2
|
+
export type { AidSettlementRepository } from "./domain/ports.js";
|
|
3
|
+
export { Reconciler } from "./application/reconciler.js";
|
|
4
|
+
export { InMemoryAidSettlementRepository } from "./infrastructure/in-memory-store.js";
|
|
5
|
+
import type { AidGrant, RedemptionClaim, ReconciliationReport } from "./domain/entities.js";
|
|
6
|
+
import type { AidSettlementRepository } from "./domain/ports.js";
|
|
7
|
+
import type { Logger } from "../shared/logger.js";
|
|
8
|
+
export declare class AidSettlementLedger {
|
|
9
|
+
private readonly repo;
|
|
10
|
+
private readonly logger;
|
|
11
|
+
constructor(options?: {
|
|
12
|
+
repo?: AidSettlementRepository;
|
|
13
|
+
logger?: Logger;
|
|
14
|
+
});
|
|
15
|
+
issueGrant(grant: AidGrant): void;
|
|
16
|
+
submitClaim(claim: RedemptionClaim): void;
|
|
17
|
+
reconcile(): ReconciliationReport;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/aid-settlement/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,QAAQ,EACR,eAAe,EACf,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAGjE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGzD,OAAO,EAAE,+BAA+B,EAAE,MAAM,qCAAqC,CAAC;AAMtF,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EACf,oBAAoB,EACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAIlD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;gBAEhC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,uBAAuB,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAKzE,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAIjC,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAIzC,SAAS,IAAI,oBAAoB;CAGlC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Application
|
|
2
|
+
export { Reconciler } from "./application/reconciler.js";
|
|
3
|
+
// Infrastructure
|
|
4
|
+
export { InMemoryAidSettlementRepository } from "./infrastructure/in-memory-store.js";
|
|
5
|
+
import { InMemoryAidSettlementRepository } from "./infrastructure/in-memory-store.js";
|
|
6
|
+
import { Reconciler } from "./application/reconciler.js";
|
|
7
|
+
export class AidSettlementLedger {
|
|
8
|
+
repo;
|
|
9
|
+
logger;
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.repo = options?.repo ?? new InMemoryAidSettlementRepository();
|
|
12
|
+
this.logger = options?.logger;
|
|
13
|
+
}
|
|
14
|
+
issueGrant(grant) {
|
|
15
|
+
this.repo.addGrant(grant);
|
|
16
|
+
}
|
|
17
|
+
submitClaim(claim) {
|
|
18
|
+
this.repo.addClaim(claim);
|
|
19
|
+
}
|
|
20
|
+
reconcile() {
|
|
21
|
+
return new Reconciler(this.repo, this.logger).reconcile();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { InMemoryStore } from "../../shared/index.js";
|
|
2
|
+
import type { AidGrant, RedemptionClaim } from "../domain/entities.js";
|
|
3
|
+
import type { AidSettlementRepository } from "../domain/ports.js";
|
|
4
|
+
export declare class InMemoryAidSettlementRepository implements AidSettlementRepository {
|
|
5
|
+
readonly grants: InMemoryStore<string, AidGrant>;
|
|
6
|
+
private readonly claims;
|
|
7
|
+
addGrant(grant: AidGrant): void;
|
|
8
|
+
addClaim(claim: RedemptionClaim): void;
|
|
9
|
+
claimsForGrant(grantId: string): readonly RedemptionClaim[];
|
|
10
|
+
grantIds(): Iterable<string>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=in-memory-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-store.d.ts","sourceRoot":"","sources":["../../../src/aid-settlement/infrastructure/in-memory-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAmB,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,qBAAa,+BAAgC,YAAW,uBAAuB;IAC7E,QAAQ,CAAC,MAAM,kCAAyC;IACxD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkD;IAEzE,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAItC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,eAAe,EAAE;IAI3D,QAAQ,IAAI,QAAQ,CAAC,MAAM,CAAC;CAG7B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { InMemoryStore, CollectionStore } from "../../shared/index.js";
|
|
2
|
+
export class InMemoryAidSettlementRepository {
|
|
3
|
+
grants = new InMemoryStore();
|
|
4
|
+
claims = new CollectionStore();
|
|
5
|
+
addGrant(grant) {
|
|
6
|
+
this.grants.set(grant.id, grant);
|
|
7
|
+
}
|
|
8
|
+
addClaim(claim) {
|
|
9
|
+
this.claims.append(claim.grantId, claim);
|
|
10
|
+
}
|
|
11
|
+
claimsForGrant(grantId) {
|
|
12
|
+
return this.claims.getAll(grantId);
|
|
13
|
+
}
|
|
14
|
+
grantIds() {
|
|
15
|
+
return this.claims.keys();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ClearanceDecision, StaffingAssignment } from "../domain/entities.js";
|
|
2
|
+
import type { CredentialRepository } from "../domain/ports.js";
|
|
3
|
+
import type { Logger } from "../../shared/logger.js";
|
|
4
|
+
export declare class ClearanceEvaluator {
|
|
5
|
+
private readonly repo;
|
|
6
|
+
private readonly logger;
|
|
7
|
+
constructor(repo: CredentialRepository, logger?: Logger);
|
|
8
|
+
evaluate(assignment: StaffingAssignment): ClearanceDecision;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=clearance-evaluator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clearance-evaluator.d.ts","sourceRoot":"","sources":["../../../src/credentialing/application/clearance-evaluator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGrD,qBAAa,kBAAkB;IAI3B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAGb,IAAI,EAAE,oBAAoB,EAC3C,MAAM,CAAC,EAAE,MAAM;IAKjB,QAAQ,CAAC,UAAU,EAAE,kBAAkB,GAAG,iBAAiB;CAuE5D"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { daysUntil } from "../../shared/date.js";
|
|
2
|
+
import { noopLogger } from "../../shared/logger.js";
|
|
3
|
+
export class ClearanceEvaluator {
|
|
4
|
+
repo;
|
|
5
|
+
logger;
|
|
6
|
+
constructor(repo, logger) {
|
|
7
|
+
this.repo = repo;
|
|
8
|
+
this.logger = logger ?? noopLogger;
|
|
9
|
+
}
|
|
10
|
+
evaluate(assignment) {
|
|
11
|
+
const start = Date.now();
|
|
12
|
+
this.logger.info("clearance evaluation started", {
|
|
13
|
+
operation: "ClearanceEvaluator.evaluate",
|
|
14
|
+
entityId: assignment.providerId,
|
|
15
|
+
});
|
|
16
|
+
const provider = this.repo.providers.get(assignment.providerId);
|
|
17
|
+
if (!provider) {
|
|
18
|
+
throw new Error(`Unknown provider ${assignment.providerId}`);
|
|
19
|
+
}
|
|
20
|
+
const credentials = this.repo.getCredentials(assignment.providerId);
|
|
21
|
+
const reasons = [];
|
|
22
|
+
const missingCredentials = [];
|
|
23
|
+
const expiringSoon = [];
|
|
24
|
+
const scheduleDate = new Date(assignment.scheduledAt);
|
|
25
|
+
if (provider.sanctionStatus !== "clear") {
|
|
26
|
+
reasons.push(`Provider sanction status is ${provider.sanctionStatus}.`);
|
|
27
|
+
}
|
|
28
|
+
for (const required of assignment.requiredCredentials) {
|
|
29
|
+
const credential = credentials.find((c) => c.type === required &&
|
|
30
|
+
c.jurisdictions.includes(assignment.jurisdiction));
|
|
31
|
+
if (!credential) {
|
|
32
|
+
missingCredentials.push(required);
|
|
33
|
+
reasons.push(`Missing ${required} credential for jurisdiction ${assignment.jurisdiction}.`);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const validUntil = new Date(credential.validUntil);
|
|
37
|
+
if (validUntil < scheduleDate) {
|
|
38
|
+
missingCredentials.push(required);
|
|
39
|
+
reasons.push(`${required} expires before the scheduled procedure.`);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const remaining = daysUntil(scheduleDate, validUntil);
|
|
43
|
+
if (remaining <= 30) {
|
|
44
|
+
expiringSoon.push(`${required} (${remaining} days remaining)`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const decision = {
|
|
48
|
+
approved: reasons.length === 0 &&
|
|
49
|
+
missingCredentials.length === 0 &&
|
|
50
|
+
provider.sanctionStatus === "clear",
|
|
51
|
+
missingCredentials,
|
|
52
|
+
expiringSoon,
|
|
53
|
+
reasons,
|
|
54
|
+
};
|
|
55
|
+
this.logger.info(decision.approved ? "clearance approved" : "clearance denied", {
|
|
56
|
+
operation: "ClearanceEvaluator.evaluate",
|
|
57
|
+
entityId: assignment.providerId,
|
|
58
|
+
result: decision.approved ? "approved" : "denied",
|
|
59
|
+
durationMs: Date.now() - start,
|
|
60
|
+
});
|
|
61
|
+
return decision;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface ClinicalCredential {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly providerId: string;
|
|
4
|
+
readonly type: string;
|
|
5
|
+
readonly jurisdictions: string[];
|
|
6
|
+
readonly validUntil: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ProviderProfile {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly specialties: string[];
|
|
12
|
+
readonly sanctionStatus: "clear" | "review" | "blocked";
|
|
13
|
+
}
|
|
14
|
+
export interface StaffingAssignment {
|
|
15
|
+
readonly providerId: string;
|
|
16
|
+
readonly facility: string;
|
|
17
|
+
readonly jurisdiction: string;
|
|
18
|
+
readonly requiredCredentials: string[];
|
|
19
|
+
readonly procedure: string;
|
|
20
|
+
readonly scheduledAt: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ClearanceDecision {
|
|
23
|
+
readonly approved: boolean;
|
|
24
|
+
readonly missingCredentials: string[];
|
|
25
|
+
readonly expiringSoon: string[];
|
|
26
|
+
readonly reasons: string[];
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=entities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../../src/credentialing/domain/entities.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;CACzD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;CAC5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReadonlyStore } from "../../shared/store.js";
|
|
2
|
+
import type { ClinicalCredential, ProviderProfile } from "./entities.js";
|
|
3
|
+
export interface CredentialRepository {
|
|
4
|
+
readonly providers: ReadonlyStore<string, ProviderProfile>;
|
|
5
|
+
getCredentials(providerId: string): readonly ClinicalCredential[];
|
|
6
|
+
addProvider(provider: ProviderProfile): void;
|
|
7
|
+
addCredential(credential: ClinicalCredential): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=ports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../src/credentialing/domain/ports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC3D,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,kBAAkB,EAAE,CAAC;IAClE,WAAW,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IAC7C,aAAa,CAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACrD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type { ClinicalCredential, ProviderProfile, StaffingAssignment, ClearanceDecision, } from "./domain/entities.js";
|
|
2
|
+
export type { CredentialRepository } from "./domain/ports.js";
|
|
3
|
+
export { ClearanceEvaluator } from "./application/clearance-evaluator.js";
|
|
4
|
+
export { InMemoryCredentialRepository } from "./infrastructure/in-memory-store.js";
|
|
5
|
+
import type { ClinicalCredential, ClearanceDecision, ProviderProfile, StaffingAssignment } from "./domain/entities.js";
|
|
6
|
+
import type { CredentialRepository } from "./domain/ports.js";
|
|
7
|
+
import type { Logger } from "../shared/logger.js";
|
|
8
|
+
export declare class CredentialRegistry {
|
|
9
|
+
private readonly repo;
|
|
10
|
+
private readonly evaluator;
|
|
11
|
+
constructor(options?: {
|
|
12
|
+
repo?: CredentialRepository;
|
|
13
|
+
logger?: Logger;
|
|
14
|
+
});
|
|
15
|
+
registerProvider(provider: ProviderProfile): void;
|
|
16
|
+
issueCredential(credential: ClinicalCredential): void;
|
|
17
|
+
evaluateAssignment(assignment: StaffingAssignment): ClearanceDecision;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/credentialing/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAG9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAG1E,OAAO,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AAMnF,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAIlD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;gBAEnC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,oBAAoB,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAKtE,gBAAgB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IAIjD,eAAe,CAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI;IAIrD,kBAAkB,CAAC,UAAU,EAAE,kBAAkB,GAAG,iBAAiB;CAGtE"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Application
|
|
2
|
+
export { ClearanceEvaluator } from "./application/clearance-evaluator.js";
|
|
3
|
+
// Infrastructure
|
|
4
|
+
export { InMemoryCredentialRepository } from "./infrastructure/in-memory-store.js";
|
|
5
|
+
import { InMemoryCredentialRepository } from "./infrastructure/in-memory-store.js";
|
|
6
|
+
import { ClearanceEvaluator } from "./application/clearance-evaluator.js";
|
|
7
|
+
export class CredentialRegistry {
|
|
8
|
+
repo;
|
|
9
|
+
evaluator;
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.repo = options?.repo ?? new InMemoryCredentialRepository();
|
|
12
|
+
this.evaluator = new ClearanceEvaluator(this.repo, options?.logger);
|
|
13
|
+
}
|
|
14
|
+
registerProvider(provider) {
|
|
15
|
+
this.repo.addProvider(provider);
|
|
16
|
+
}
|
|
17
|
+
issueCredential(credential) {
|
|
18
|
+
this.repo.addCredential(credential);
|
|
19
|
+
}
|
|
20
|
+
evaluateAssignment(assignment) {
|
|
21
|
+
return this.evaluator.evaluate(assignment);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { InMemoryStore } from "../../shared/index.js";
|
|
2
|
+
import type { ClinicalCredential, ProviderProfile } from "../domain/entities.js";
|
|
3
|
+
import type { CredentialRepository } from "../domain/ports.js";
|
|
4
|
+
export declare class InMemoryCredentialRepository implements CredentialRepository {
|
|
5
|
+
readonly providers: InMemoryStore<string, ProviderProfile>;
|
|
6
|
+
private readonly credentials;
|
|
7
|
+
addProvider(provider: ProviderProfile): void;
|
|
8
|
+
addCredential(credential: ClinicalCredential): void;
|
|
9
|
+
getCredentials(providerId: string): readonly ClinicalCredential[];
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=in-memory-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-store.d.ts","sourceRoot":"","sources":["../../../src/credentialing/infrastructure/in-memory-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAmB,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,qBAAa,4BAA6B,YAAW,oBAAoB;IACvE,QAAQ,CAAC,SAAS,yCAAgD;IAClE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAGxB;IAEJ,WAAW,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IAI5C,aAAa,CAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI;IAInD,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,kBAAkB,EAAE;CAGlE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { InMemoryStore, CollectionStore } from "../../shared/index.js";
|
|
2
|
+
export class InMemoryCredentialRepository {
|
|
3
|
+
providers = new InMemoryStore();
|
|
4
|
+
credentials = new CollectionStore();
|
|
5
|
+
addProvider(provider) {
|
|
6
|
+
this.providers.set(provider.id, provider);
|
|
7
|
+
}
|
|
8
|
+
addCredential(credential) {
|
|
9
|
+
this.credentials.append(credential.providerId, credential);
|
|
10
|
+
}
|
|
11
|
+
getCredentials(providerId) {
|
|
12
|
+
return this.credentials.getAll(providerId);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { HsmKeyPair, HsmSignatureResult } from "../domain/entities.js";
|
|
2
|
+
import type { AuditLog, KeyStore } from "../domain/ports.js";
|
|
3
|
+
/**
|
|
4
|
+
* EC P-256 asymmetric operations — signing, verification, key export.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors a PKCS#11 CKM_ECDSA / CKM_EC_KEY_PAIR_GEN subset.
|
|
7
|
+
* Ref: PKCS#11 v3.1, §2.3.6 — https://docs.oasis-open.org/pkcs11/pkcs11-curr/v3.1/pkcs11-curr-v3.1.html
|
|
8
|
+
*
|
|
9
|
+
* Note: Domain entities store keys as PEM strings (infrastructure-agnostic).
|
|
10
|
+
* This service converts to/from KeyObject for cryptographic operations.
|
|
11
|
+
*/
|
|
12
|
+
export declare class AsymmetricKeyService {
|
|
13
|
+
private readonly keyStore;
|
|
14
|
+
private readonly audit;
|
|
15
|
+
private readonly slotId;
|
|
16
|
+
constructor(keyStore: KeyStore, audit: AuditLog, slotId: string);
|
|
17
|
+
generateKeyPair(keyLabel: string): HsmKeyPair;
|
|
18
|
+
sign(keyLabel: string, data: string): HsmSignatureResult;
|
|
19
|
+
verify(keyLabel: string, data: string, signature: string): boolean;
|
|
20
|
+
exportPublicKey(keyLabel: string): string;
|
|
21
|
+
private requireAsymmetric;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=asymmetric-key-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asymmetric-key-service.d.ts","sourceRoot":"","sources":["../../../src/hsm/application/asymmetric-key-service.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,UAAU,EACV,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE7D;;;;;;;;GAQG;AACH,qBAAa,oBAAoB;IAE7B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAFN,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,QAAQ,EACf,MAAM,EAAE,MAAM;IAGjC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU;IA8C7C,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,kBAAkB;IA4BxD,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAoBlE,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAMzC,OAAO,CAAC,iBAAiB;CAY1B"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { createPrivateKey, createPublicKey, createSign, createVerify, generateKeyPairSync, randomBytes, } from "node:crypto";
|
|
2
|
+
import { sha256hex } from "../../shared/crypto.js";
|
|
3
|
+
/**
|
|
4
|
+
* EC P-256 asymmetric operations — signing, verification, key export.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors a PKCS#11 CKM_ECDSA / CKM_EC_KEY_PAIR_GEN subset.
|
|
7
|
+
* Ref: PKCS#11 v3.1, §2.3.6 — https://docs.oasis-open.org/pkcs11/pkcs11-curr/v3.1/pkcs11-curr-v3.1.html
|
|
8
|
+
*
|
|
9
|
+
* Note: Domain entities store keys as PEM strings (infrastructure-agnostic).
|
|
10
|
+
* This service converts to/from KeyObject for cryptographic operations.
|
|
11
|
+
*/
|
|
12
|
+
export class AsymmetricKeyService {
|
|
13
|
+
keyStore;
|
|
14
|
+
audit;
|
|
15
|
+
slotId;
|
|
16
|
+
constructor(keyStore, audit, slotId) {
|
|
17
|
+
this.keyStore = keyStore;
|
|
18
|
+
this.audit = audit;
|
|
19
|
+
this.slotId = slotId;
|
|
20
|
+
}
|
|
21
|
+
generateKeyPair(keyLabel) {
|
|
22
|
+
if (this.keyStore.has(keyLabel)) {
|
|
23
|
+
throw new Error(`HSM key already exists: ${keyLabel}`);
|
|
24
|
+
}
|
|
25
|
+
const { privateKey, publicKey } = generateKeyPairSync("ec", {
|
|
26
|
+
namedCurve: "P-256",
|
|
27
|
+
});
|
|
28
|
+
const createdAt = new Date().toISOString();
|
|
29
|
+
const handle = `hsm:${this.slotId}:${keyLabel}:${randomBytes(8).toString("hex")}`;
|
|
30
|
+
// Export to PEM for storage (domain stays infrastructure-agnostic)
|
|
31
|
+
const privateKeyPem = privateKey.export({
|
|
32
|
+
type: "pkcs8",
|
|
33
|
+
format: "pem",
|
|
34
|
+
});
|
|
35
|
+
const publicKeyPem = publicKey.export({
|
|
36
|
+
type: "spki",
|
|
37
|
+
format: "pem",
|
|
38
|
+
});
|
|
39
|
+
// Type guard: PEM format always returns string
|
|
40
|
+
if (typeof privateKeyPem !== "string" || typeof publicKeyPem !== "string") {
|
|
41
|
+
throw new Error("HSM: unexpected binary output from PEM export");
|
|
42
|
+
}
|
|
43
|
+
this.keyStore.set(keyLabel, {
|
|
44
|
+
kind: "asymmetric",
|
|
45
|
+
keyLabel,
|
|
46
|
+
privateKeyPem,
|
|
47
|
+
publicKeyPem,
|
|
48
|
+
namedCurve: "P-256",
|
|
49
|
+
createdAt,
|
|
50
|
+
});
|
|
51
|
+
this.audit.record("generateKeyPair", keyLabel, "success");
|
|
52
|
+
return {
|
|
53
|
+
keyLabel,
|
|
54
|
+
keyType: "EC",
|
|
55
|
+
namedCurve: "P-256",
|
|
56
|
+
publicKeyPem,
|
|
57
|
+
privateKeyHandle: handle,
|
|
58
|
+
createdAt,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
sign(keyLabel, data) {
|
|
62
|
+
const entry = this.requireAsymmetric(keyLabel);
|
|
63
|
+
const timestamp = new Date().toISOString();
|
|
64
|
+
// Convert PEM back to KeyObject for signing
|
|
65
|
+
const privateKey = createPrivateKey(entry.privateKeyPem);
|
|
66
|
+
const signer = createSign("SHA256");
|
|
67
|
+
signer.update(data);
|
|
68
|
+
signer.end();
|
|
69
|
+
const signature = signer.sign(privateKey).toString("hex");
|
|
70
|
+
const hsmAttestation = sha256hex(`${this.slotId}:${keyLabel}:${timestamp}:${signature}`);
|
|
71
|
+
this.audit.record("sign", keyLabel, "success");
|
|
72
|
+
return {
|
|
73
|
+
keyLabel,
|
|
74
|
+
algorithm: "ecdsa-sha256",
|
|
75
|
+
signature,
|
|
76
|
+
publicKeyPem: entry.publicKeyPem,
|
|
77
|
+
timestamp,
|
|
78
|
+
hsmAttestation,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
verify(keyLabel, data, signature) {
|
|
82
|
+
const entry = this.requireAsymmetric(keyLabel);
|
|
83
|
+
// Convert PEM back to KeyObject for verification
|
|
84
|
+
const publicKey = createPublicKey(entry.publicKeyPem);
|
|
85
|
+
const verifier = createVerify("SHA256");
|
|
86
|
+
verifier.update(data);
|
|
87
|
+
verifier.end();
|
|
88
|
+
const valid = verifier.verify(publicKey, Buffer.from(signature, "hex"));
|
|
89
|
+
this.audit.record("verify", keyLabel, "success", valid ? "valid" : "invalid");
|
|
90
|
+
return valid;
|
|
91
|
+
}
|
|
92
|
+
exportPublicKey(keyLabel) {
|
|
93
|
+
const entry = this.requireAsymmetric(keyLabel);
|
|
94
|
+
this.audit.record("exportPublicKey", keyLabel, "success");
|
|
95
|
+
return entry.publicKeyPem;
|
|
96
|
+
}
|
|
97
|
+
requireAsymmetric(keyLabel) {
|
|
98
|
+
const entry = this.keyStore.get(keyLabel);
|
|
99
|
+
if (!entry) {
|
|
100
|
+
this.audit.record("keyLookup", keyLabel, "failed", "key not found");
|
|
101
|
+
throw new Error(`HSM key not found: ${keyLabel}`);
|
|
102
|
+
}
|
|
103
|
+
if (entry.kind !== "asymmetric") {
|
|
104
|
+
this.audit.record("keyLookup", keyLabel, "failed", "unexpected key type");
|
|
105
|
+
throw new Error(`HSM key '${keyLabel}' is not an asymmetric key`);
|
|
106
|
+
}
|
|
107
|
+
return entry;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { EncryptedRecord, EnvelopeEncryptionResult, WrappedKey } from "../domain/entities.js";
|
|
2
|
+
import type { AuditLog } from "../domain/ports.js";
|
|
3
|
+
import type { SymmetricKeyService } from "./symmetric-key-service.js";
|
|
4
|
+
/**
|
|
5
|
+
* DEK/KEK envelope encryption — ephemeral DEK wrapped by a stored KEK.
|
|
6
|
+
*
|
|
7
|
+
* The resulting ciphertext is suitable for storage on a distributed ledger:
|
|
8
|
+
* - encryptedRecord = AES-256-GCM ciphertext of the payload
|
|
9
|
+
* - wrappedDek = GCM-wrapped DEK (only the HSM can unwrap it)
|
|
10
|
+
*/
|
|
11
|
+
export declare class EnvelopeEncryptionService {
|
|
12
|
+
private readonly symmetric;
|
|
13
|
+
private readonly audit;
|
|
14
|
+
constructor(symmetric: SymmetricKeyService, audit: AuditLog);
|
|
15
|
+
encrypt(kekLabel: string, plaintext: string): EnvelopeEncryptionResult;
|
|
16
|
+
decrypt(wrappedDek: WrappedKey, encryptedRecord: EncryptedRecord): string;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=envelope-encryption-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope-encryption-service.d.ts","sourceRoot":"","sources":["../../../src/hsm/application/envelope-encryption-service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,wBAAwB,EACxB,UAAU,EACX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE;;;;;;GAMG;AACH,qBAAa,yBAAyB;IAElC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,SAAS,EAAE,mBAAmB,EAC9B,KAAK,EAAE,QAAQ;IAGlC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,wBAAwB;IAyBtE,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,GAAG,MAAM;CA4B1E"}
|