@brightchain/brightchain-api-lib 0.14.0 → 0.16.0
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/package.json +5 -5
- package/src/browser.d.ts +13 -0
- package/src/browser.d.ts.map +1 -0
- package/src/browser.js +16 -0
- package/src/browser.js.map +1 -0
- package/src/index.d.ts +4 -1
- package/src/index.d.ts.map +1 -1
- package/src/index.js +6 -1
- package/src/index.js.map +1 -1
- package/src/lib/application-base.d.ts +8 -37
- package/src/lib/application-base.d.ts.map +1 -1
- package/src/lib/application-base.js +8 -80
- package/src/lib/application-base.js.map +1 -1
- package/src/lib/application.d.ts +37 -7
- package/src/lib/application.d.ts.map +1 -1
- package/src/lib/application.js +130 -118
- package/src/lib/application.js.map +1 -1
- package/src/lib/auth/aclEnforcedAvailability.d.ts +57 -0
- package/src/lib/auth/aclEnforcedAvailability.d.ts.map +1 -0
- package/src/lib/auth/aclEnforcedAvailability.js +87 -0
- package/src/lib/auth/aclEnforcedAvailability.js.map +1 -0
- package/src/lib/auth/aclEnforcedBlockStore.d.ts +66 -0
- package/src/lib/auth/aclEnforcedBlockStore.d.ts.map +1 -0
- package/src/lib/auth/aclEnforcedBlockStore.js +83 -0
- package/src/lib/auth/aclEnforcedBlockStore.js.map +1 -0
- package/src/lib/auth/ecdsaNodeAuthenticator.d.ts +46 -0
- package/src/lib/auth/ecdsaNodeAuthenticator.d.ts.map +1 -0
- package/src/lib/auth/ecdsaNodeAuthenticator.js +110 -0
- package/src/lib/auth/ecdsaNodeAuthenticator.js.map +1 -0
- package/src/lib/auth/index.d.ts +7 -0
- package/src/lib/auth/index.d.ts.map +1 -0
- package/src/lib/auth/index.js +13 -0
- package/src/lib/auth/index.js.map +1 -0
- package/src/lib/auth/poolAclBootstrap.d.ts +36 -0
- package/src/lib/auth/poolAclBootstrap.d.ts.map +1 -0
- package/src/lib/auth/poolAclBootstrap.js +64 -0
- package/src/lib/auth/poolAclBootstrap.js.map +1 -0
- package/src/lib/auth/poolAclStore.d.ts +77 -0
- package/src/lib/auth/poolAclStore.d.ts.map +1 -0
- package/src/lib/auth/poolAclStore.js +189 -0
- package/src/lib/auth/poolAclStore.js.map +1 -0
- package/src/lib/auth/poolAclUpdater.d.ts +79 -0
- package/src/lib/auth/poolAclUpdater.d.ts.map +1 -0
- package/src/lib/auth/poolAclUpdater.js +144 -0
- package/src/lib/auth/poolAclUpdater.js.map +1 -0
- package/src/lib/availability/availabilityService.d.ts +2 -2
- package/src/lib/availability/availabilityService.d.ts.map +1 -1
- package/src/lib/availability/availabilityService.js +12 -5
- package/src/lib/availability/availabilityService.js.map +1 -1
- package/src/lib/availability/blockRegistry.d.ts +45 -3
- package/src/lib/availability/blockRegistry.d.ts.map +1 -1
- package/src/lib/availability/blockRegistry.js +123 -5
- package/src/lib/availability/blockRegistry.js.map +1 -1
- package/src/lib/availability/discoveryProtocol.d.ts +30 -1
- package/src/lib/availability/discoveryProtocol.d.ts.map +1 -1
- package/src/lib/availability/discoveryProtocol.js +76 -0
- package/src/lib/availability/discoveryProtocol.js.map +1 -1
- package/src/lib/availability/gossipService.d.ts +45 -6
- package/src/lib/availability/gossipService.d.ts.map +1 -1
- package/src/lib/availability/gossipService.js +177 -5
- package/src/lib/availability/gossipService.js.map +1 -1
- package/src/lib/availability/reconciliationService.d.ts +88 -1
- package/src/lib/availability/reconciliationService.d.ts.map +1 -1
- package/src/lib/availability/reconciliationService.js +246 -48
- package/src/lib/availability/reconciliationService.js.map +1 -1
- package/src/lib/blockFetch/blockFetcher.d.ts +100 -0
- package/src/lib/blockFetch/blockFetcher.d.ts.map +1 -0
- package/src/lib/blockFetch/blockFetcher.js +279 -0
- package/src/lib/blockFetch/blockFetcher.js.map +1 -0
- package/src/lib/blockFetch/fetchQueue.d.ts +88 -0
- package/src/lib/blockFetch/fetchQueue.d.ts.map +1 -0
- package/src/lib/blockFetch/fetchQueue.js +204 -0
- package/src/lib/blockFetch/fetchQueue.js.map +1 -0
- package/src/lib/blockFetch/httpBlockFetchTransport.d.ts +65 -0
- package/src/lib/blockFetch/httpBlockFetchTransport.d.ts.map +1 -0
- package/src/lib/blockFetch/httpBlockFetchTransport.js +104 -0
- package/src/lib/blockFetch/httpBlockFetchTransport.js.map +1 -0
- package/src/lib/blockFetch/index.d.ts +10 -0
- package/src/lib/blockFetch/index.d.ts.map +1 -0
- package/src/lib/blockFetch/index.js +13 -0
- package/src/lib/blockFetch/index.js.map +1 -0
- package/src/lib/constants.js +2 -2
- package/src/lib/constants.js.map +1 -1
- package/src/lib/controllers/api/blocks.d.ts.map +1 -1
- package/src/lib/controllers/api/blocks.js +290 -290
- package/src/lib/controllers/api/blocks.js.map +1 -1
- package/src/lib/controllers/api/brightpass.d.ts +72 -0
- package/src/lib/controllers/api/brightpass.d.ts.map +1 -0
- package/src/lib/controllers/api/brightpass.js +577 -0
- package/src/lib/controllers/api/brightpass.js.map +1 -0
- package/src/lib/controllers/api/channels.d.ts +122 -0
- package/src/lib/controllers/api/channels.d.ts.map +1 -0
- package/src/lib/controllers/api/channels.js +701 -0
- package/src/lib/controllers/api/channels.js.map +1 -0
- package/src/lib/controllers/api/conversations.d.ts +89 -0
- package/src/lib/controllers/api/conversations.d.ts.map +1 -0
- package/src/lib/controllers/api/conversations.js +259 -0
- package/src/lib/controllers/api/conversations.js.map +1 -0
- package/src/lib/controllers/api/emails.d.ts +122 -0
- package/src/lib/controllers/api/emails.d.ts.map +1 -0
- package/src/lib/controllers/api/emails.js +494 -0
- package/src/lib/controllers/api/emails.js.map +1 -0
- package/src/lib/controllers/api/energy.d.ts.map +1 -1
- package/src/lib/controllers/api/energy.js +93 -93
- package/src/lib/controllers/api/energy.js.map +1 -1
- package/src/lib/controllers/api/explodingMessages.d.ts +79 -0
- package/src/lib/controllers/api/explodingMessages.d.ts.map +1 -0
- package/src/lib/controllers/api/explodingMessages.js +378 -0
- package/src/lib/controllers/api/explodingMessages.js.map +1 -0
- package/src/lib/controllers/api/groups.d.ts +94 -0
- package/src/lib/controllers/api/groups.d.ts.map +1 -0
- package/src/lib/controllers/api/groups.js +484 -0
- package/src/lib/controllers/api/groups.js.map +1 -0
- package/src/lib/controllers/api/i18n.d.ts.map +1 -1
- package/src/lib/controllers/api/i18n.js +8 -8
- package/src/lib/controllers/api/i18n.js.map +1 -1
- package/src/lib/controllers/api/index.d.ts +6 -0
- package/src/lib/controllers/api/index.d.ts.map +1 -1
- package/src/lib/controllers/api/index.js +6 -0
- package/src/lib/controllers/api/index.js.map +1 -1
- package/src/lib/controllers/api/messages.d.ts.map +1 -1
- package/src/lib/controllers/api/messages.js +2 -1
- package/src/lib/controllers/api/messages.js.map +1 -1
- package/src/lib/controllers/api/quorum.d.ts.map +1 -1
- package/src/lib/controllers/api/quorum.js +483 -483
- package/src/lib/controllers/api/quorum.js.map +1 -1
- package/src/lib/controllers/api/sessions.d.ts.map +1 -1
- package/src/lib/controllers/api/sessions.js +8 -8
- package/src/lib/controllers/api/sessions.js.map +1 -1
- package/src/lib/controllers/api/sync.d.ts +38 -2
- package/src/lib/controllers/api/sync.d.ts.map +1 -1
- package/src/lib/controllers/api/sync.js +89 -0
- package/src/lib/controllers/api/sync.js.map +1 -1
- package/src/lib/controllers/api/user.d.ts.map +1 -1
- package/src/lib/controllers/api/user.js +180 -180
- package/src/lib/controllers/api/user.js.map +1 -1
- package/src/lib/controllers/crypto/gitController.d.ts +70 -0
- package/src/lib/controllers/crypto/gitController.d.ts.map +1 -0
- package/src/lib/controllers/crypto/gitController.js +306 -0
- package/src/lib/controllers/crypto/gitController.js.map +1 -0
- package/src/lib/controllers/crypto/index.d.ts +3 -0
- package/src/lib/controllers/crypto/index.d.ts.map +1 -0
- package/src/lib/controllers/crypto/index.js +6 -0
- package/src/lib/controllers/crypto/index.js.map +1 -0
- package/src/lib/controllers/crypto/walletController.d.ts +64 -0
- package/src/lib/controllers/crypto/walletController.d.ts.map +1 -0
- package/src/lib/controllers/crypto/walletController.js +260 -0
- package/src/lib/controllers/crypto/walletController.js.map +1 -0
- package/src/lib/controllers/identity/deviceController.d.ts +96 -0
- package/src/lib/controllers/identity/deviceController.d.ts.map +1 -0
- package/src/lib/controllers/identity/deviceController.js +355 -0
- package/src/lib/controllers/identity/deviceController.js.map +1 -0
- package/src/lib/controllers/identity/directoryController.d.ts +75 -0
- package/src/lib/controllers/identity/directoryController.d.ts.map +1 -0
- package/src/lib/controllers/identity/directoryController.js +288 -0
- package/src/lib/controllers/identity/directoryController.js.map +1 -0
- package/src/lib/controllers/identity/identityProofController.d.ts +94 -0
- package/src/lib/controllers/identity/identityProofController.d.ts.map +1 -0
- package/src/lib/controllers/identity/identityProofController.js +454 -0
- package/src/lib/controllers/identity/identityProofController.js.map +1 -0
- package/src/lib/controllers/identity/index.d.ts +4 -0
- package/src/lib/controllers/identity/index.d.ts.map +1 -0
- package/src/lib/controllers/identity/index.js +7 -0
- package/src/lib/controllers/identity/index.js.map +1 -0
- package/src/lib/controllers/index.d.ts +2 -0
- package/src/lib/controllers/index.d.ts.map +1 -1
- package/src/lib/controllers/index.js +2 -0
- package/src/lib/controllers/index.js.map +1 -1
- package/src/lib/encryption/encryptedMetadataService.d.ts +87 -0
- package/src/lib/encryption/encryptedMetadataService.d.ts.map +1 -0
- package/src/lib/encryption/encryptedMetadataService.js +224 -0
- package/src/lib/encryption/encryptedMetadataService.js.map +1 -0
- package/src/lib/encryption/encryptionAwareReplication.d.ts +76 -0
- package/src/lib/encryption/encryptionAwareReplication.d.ts.map +1 -0
- package/src/lib/encryption/encryptionAwareReplication.js +116 -0
- package/src/lib/encryption/encryptionAwareReplication.js.map +1 -0
- package/src/lib/encryption/errors.d.ts +49 -0
- package/src/lib/encryption/errors.d.ts.map +1 -0
- package/src/lib/encryption/errors.js +80 -0
- package/src/lib/encryption/errors.js.map +1 -0
- package/src/lib/encryption/index.d.ts +6 -0
- package/src/lib/encryption/index.d.ts.map +1 -0
- package/src/lib/encryption/index.js +9 -0
- package/src/lib/encryption/index.js.map +1 -0
- package/src/lib/encryption/poolEncryptionService.d.ts +94 -0
- package/src/lib/encryption/poolEncryptionService.d.ts.map +1 -0
- package/src/lib/encryption/poolEncryptionService.js +252 -0
- package/src/lib/encryption/poolEncryptionService.js.map +1 -0
- package/src/lib/encryption/poolKeyManager.d.ts +82 -0
- package/src/lib/encryption/poolKeyManager.d.ts.map +1 -0
- package/src/lib/encryption/poolKeyManager.js +156 -0
- package/src/lib/encryption/poolKeyManager.js.map +1 -0
- package/src/lib/environment.d.ts +3 -0
- package/src/lib/environment.d.ts.map +1 -1
- package/src/lib/environment.js +5 -0
- package/src/lib/environment.js.map +1 -1
- package/src/lib/interfaces/application.d.ts +7 -1
- package/src/lib/interfaces/application.d.ts.map +1 -1
- package/src/lib/interfaces/brightchain-init-result.d.ts +17 -0
- package/src/lib/interfaces/brightchain-init-result.d.ts.map +1 -0
- package/src/lib/interfaces/brightchain-init-result.js +9 -0
- package/src/lib/interfaces/brightchain-init-result.js.map +1 -0
- package/src/lib/interfaces/environment.d.ts +7 -1
- package/src/lib/interfaces/environment.d.ts.map +1 -1
- package/src/lib/interfaces/index.d.ts +1 -1
- package/src/lib/interfaces/index.d.ts.map +1 -1
- package/src/lib/interfaces/requests/getBlockDataRequest.d.ts +12 -0
- package/src/lib/interfaces/requests/getBlockDataRequest.d.ts.map +1 -0
- package/src/lib/interfaces/{blockStore.js → requests/getBlockDataRequest.js} +1 -1
- package/src/lib/interfaces/requests/getBlockDataRequest.js.map +1 -0
- package/src/lib/interfaces/requests/index.d.ts +1 -0
- package/src/lib/interfaces/requests/index.d.ts.map +1 -1
- package/src/lib/routers/api.d.ts +54 -1
- package/src/lib/routers/api.d.ts.map +1 -1
- package/src/lib/routers/api.js +77 -0
- package/src/lib/routers/api.js.map +1 -1
- package/src/lib/routers/app.d.ts +22 -14
- package/src/lib/routers/app.d.ts.map +1 -1
- package/src/lib/routers/app.js +28 -116
- package/src/lib/routers/app.js.map +1 -1
- package/src/lib/services/blockStore.d.ts +5 -2
- package/src/lib/services/blockStore.d.ts.map +1 -1
- package/src/lib/services/blockStore.js +4 -0
- package/src/lib/services/blockStore.js.map +1 -1
- package/src/lib/services/brightpass/auditLogger.d.ts +77 -0
- package/src/lib/services/brightpass/auditLogger.d.ts.map +1 -0
- package/src/lib/services/brightpass/auditLogger.js +184 -0
- package/src/lib/services/brightpass/auditLogger.js.map +1 -0
- package/src/lib/services/brightpass/vaultEncryption.d.ts +82 -0
- package/src/lib/services/brightpass/vaultEncryption.d.ts.map +1 -0
- package/src/lib/services/brightpass/vaultEncryption.js +144 -0
- package/src/lib/services/brightpass/vaultEncryption.js.map +1 -0
- package/src/lib/services/brightpass.d.ts +294 -0
- package/src/lib/services/brightpass.d.ts.map +1 -0
- package/src/lib/services/brightpass.js +1260 -0
- package/src/lib/services/brightpass.js.map +1 -0
- package/src/lib/services/brightpass.property.helpers.d.ts +23 -0
- package/src/lib/services/brightpass.property.helpers.d.ts.map +1 -0
- package/src/lib/services/brightpass.property.helpers.js +113 -0
- package/src/lib/services/brightpass.property.helpers.js.map +1 -0
- package/src/lib/services/eventNotificationSystem.d.ts +69 -3
- package/src/lib/services/eventNotificationSystem.d.ts.map +1 -1
- package/src/lib/services/eventNotificationSystem.js +200 -0
- package/src/lib/services/eventNotificationSystem.js.map +1 -1
- package/src/lib/services/expirationScheduler.d.ts +90 -0
- package/src/lib/services/expirationScheduler.d.ts.map +1 -0
- package/src/lib/services/expirationScheduler.js +131 -0
- package/src/lib/services/expirationScheduler.js.map +1 -0
- package/src/lib/services/fecUsageExample.d.ts +2 -2
- package/src/lib/services/index.d.ts +2 -0
- package/src/lib/services/index.d.ts.map +1 -1
- package/src/lib/services/index.js +2 -0
- package/src/lib/services/index.js.map +1 -1
- package/src/lib/services/paginationService.d.ts +18 -0
- package/src/lib/services/paginationService.d.ts.map +1 -0
- package/src/lib/services/paginationService.js +32 -0
- package/src/lib/services/paginationService.js.map +1 -0
- package/src/lib/services/presenceService.d.ts +76 -0
- package/src/lib/services/presenceService.d.ts.map +1 -0
- package/src/lib/services/presenceService.js +143 -0
- package/src/lib/services/presenceService.js.map +1 -0
- package/src/lib/services/wireConversationPromotion.d.ts +23 -0
- package/src/lib/services/wireConversationPromotion.d.ts.map +1 -0
- package/src/lib/services/wireConversationPromotion.js +26 -0
- package/src/lib/services/wireConversationPromotion.js.map +1 -0
- package/src/lib/stores/availabilityAwareBlockStore.d.ts +115 -10
- package/src/lib/stores/availabilityAwareBlockStore.d.ts.map +1 -1
- package/src/lib/stores/availabilityAwareBlockStore.js +267 -23
- package/src/lib/stores/availabilityAwareBlockStore.js.map +1 -1
- package/src/lib/stores/diskBlockAsyncStore.d.ts +81 -2
- package/src/lib/stores/diskBlockAsyncStore.d.ts.map +1 -1
- package/src/lib/stores/diskBlockAsyncStore.js +297 -10
- package/src/lib/stores/diskBlockAsyncStore.js.map +1 -1
- package/src/lib/upstream-stubs.d.ts +36 -0
- package/src/lib/upstream-stubs.d.ts.map +1 -0
- package/src/lib/upstream-stubs.js +43 -0
- package/src/lib/upstream-stubs.js.map +1 -0
- package/src/lib/utils/communicationValidation.d.ts +44 -0
- package/src/lib/utils/communicationValidation.d.ts.map +1 -0
- package/src/lib/utils/communicationValidation.js +291 -0
- package/src/lib/utils/communicationValidation.js.map +1 -0
- package/src/lib/utils/emailValidation.d.ts +19 -0
- package/src/lib/utils/emailValidation.d.ts.map +1 -0
- package/src/lib/utils/emailValidation.js +232 -0
- package/src/lib/utils/emailValidation.js.map +1 -0
- package/src/lib/interfaces/blockStore.d.ts +0 -7
- package/src/lib/interfaces/blockStore.d.ts.map +0 -1
- package/src/lib/interfaces/blockStore.js.map +0 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pool ACL Bootstrap - creates the initial ACL when a new pool is created.
|
|
4
|
+
*
|
|
5
|
+
* Derives the creator's public key and node ID from their private key,
|
|
6
|
+
* creates an ACL with the creator as sole Admin, signs it, and stores it
|
|
7
|
+
* via PoolACLStore.
|
|
8
|
+
*
|
|
9
|
+
* @see Requirements 12.1, 12.2, 12.3, 12.4, 12.5, 12.6
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.PoolACLBootstrap = void 0;
|
|
13
|
+
const tslib_1 = require("tslib");
|
|
14
|
+
const brightchain_lib_1 = require("@brightchain/brightchain-lib");
|
|
15
|
+
const crypto = tslib_1.__importStar(require("crypto"));
|
|
16
|
+
const ecdsaNodeAuthenticator_1 = require("./ecdsaNodeAuthenticator");
|
|
17
|
+
class PoolACLBootstrap {
|
|
18
|
+
constructor(store, authenticator) {
|
|
19
|
+
this.store = store;
|
|
20
|
+
this.authenticator = authenticator ?? new ecdsaNodeAuthenticator_1.ECDSANodeAuthenticator();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Bootstrap a new pool by creating and signing the initial ACL.
|
|
24
|
+
*
|
|
25
|
+
* - Derives the creator's public key and node ID from the private key
|
|
26
|
+
* - Creates an ACL with the creator as sole Admin member
|
|
27
|
+
* - Sets publicRead/publicWrite from options (default false)
|
|
28
|
+
* - Signs the ACL with the creator's key via PoolACLStore.storeACL()
|
|
29
|
+
* - Returns the block ID and the created ACL
|
|
30
|
+
*/
|
|
31
|
+
async bootstrapPool(poolId, creatorPrivateKey, options) {
|
|
32
|
+
// Derive creator's public key and node ID
|
|
33
|
+
const ecdh = crypto.createECDH('secp256k1');
|
|
34
|
+
ecdh.setPrivateKey(Buffer.from(creatorPrivateKey));
|
|
35
|
+
const publicKey = new Uint8Array(ecdh.getPublicKey());
|
|
36
|
+
const creatorNodeId = this.authenticator.deriveNodeId(publicKey);
|
|
37
|
+
const now = new Date();
|
|
38
|
+
// Create the initial ACL with creator as sole Admin
|
|
39
|
+
const acl = {
|
|
40
|
+
poolId,
|
|
41
|
+
owner: creatorNodeId,
|
|
42
|
+
members: [
|
|
43
|
+
{
|
|
44
|
+
nodeId: creatorNodeId,
|
|
45
|
+
permissions: [brightchain_lib_1.PoolPermission.Admin],
|
|
46
|
+
addedAt: now,
|
|
47
|
+
addedBy: creatorNodeId,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
publicRead: options?.publicRead ?? false,
|
|
51
|
+
publicWrite: options?.publicWrite ?? false,
|
|
52
|
+
approvalSignatures: [],
|
|
53
|
+
version: 1,
|
|
54
|
+
updatedAt: now,
|
|
55
|
+
};
|
|
56
|
+
// Sign and store the ACL
|
|
57
|
+
const aclBlockId = await this.store.storeACL(acl, creatorPrivateKey);
|
|
58
|
+
// Load back the stored ACL (includes the approval signature)
|
|
59
|
+
const storedAcl = await this.store.loadACL(aclBlockId);
|
|
60
|
+
return { aclBlockId, acl: storedAcl };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.PoolACLBootstrap = PoolACLBootstrap;
|
|
64
|
+
//# sourceMappingURL=poolAclBootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poolAclBootstrap.js","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/auth/poolAclBootstrap.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;AAGH,kEAA8D;AAC9D,uDAAiC;AAEjC,qEAAkE;AAalE,MAAa,gBAAgB;IAI3B,YAAY,KAAmB,EAAE,aAAsC;QACrE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,aAAa,GAAG,aAAa,IAAI,IAAI,+CAAsB,EAAE,CAAC;IACrE,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,aAAa,CACjB,MAAc,EACd,iBAA6B,EAC7B,OAA8B;QAE9B,0CAA0C;QAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACtD,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAEjE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QAEvB,oDAAoD;QACpD,MAAM,GAAG,GAAqB;YAC5B,MAAM;YACN,KAAK,EAAE,aAAa;YACpB,OAAO,EAAE;gBACP;oBACE,MAAM,EAAE,aAAa;oBACrB,WAAW,EAAE,CAAC,gCAAc,CAAC,KAAK,CAAC;oBACnC,OAAO,EAAE,GAAG;oBACZ,OAAO,EAAE,aAAa;iBACvB;aACF;YACD,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,KAAK;YACxC,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,KAAK;YAC1C,kBAAkB,EAAE,EAAE;YACtB,OAAO,EAAE,CAAC;YACV,SAAS,EAAE,GAAG;SACf,CAAC;QAEF,yBAAyB;QACzB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;QAErE,6DAA6D;QAC7D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAEvD,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;IACxC,CAAC;CACF;AA1DD,4CA0DC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pool ACL Store - stores and retrieves ACLs as signed blocks.
|
|
3
|
+
*
|
|
4
|
+
* Each ACL is serialized to JSON (without approvalSignatures), signed with
|
|
5
|
+
* the admin's ECDSA key, and stored as a block. On retrieval, the signature
|
|
6
|
+
* is verified against the first approval signature's public key.
|
|
7
|
+
*
|
|
8
|
+
* ACL chain: each update references the previous ACL block ID via
|
|
9
|
+
* `previousAclBlockId`, forming an auditable linked list.
|
|
10
|
+
*
|
|
11
|
+
* @see Requirements 11.1, 13.3
|
|
12
|
+
*/
|
|
13
|
+
import type { IPoolACL } from '@brightchain/brightchain-lib';
|
|
14
|
+
import { ECDSANodeAuthenticator } from './ecdsaNodeAuthenticator';
|
|
15
|
+
/**
|
|
16
|
+
* The on-disk format for a signed ACL block.
|
|
17
|
+
* `aclJson` is the ACL without approvalSignatures; `signatures` carries
|
|
18
|
+
* the admin signatures as hex strings alongside their node IDs.
|
|
19
|
+
*/
|
|
20
|
+
export interface SignedACLBlock {
|
|
21
|
+
aclJson: string;
|
|
22
|
+
signatures: Array<{
|
|
23
|
+
nodeId: string;
|
|
24
|
+
signature: string;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Stores and retrieves Pool ACLs as signed blocks.
|
|
29
|
+
*
|
|
30
|
+
* Uses an in-memory Map for block storage (actual block store integration
|
|
31
|
+
* comes in a later task). Block IDs are SHA-256 hashes of the stored content.
|
|
32
|
+
*/
|
|
33
|
+
export declare class PoolACLStore {
|
|
34
|
+
protected readonly blocks: Map<string, Uint8Array<ArrayBufferLike>>;
|
|
35
|
+
private readonly authenticator;
|
|
36
|
+
constructor(authenticator?: ECDSANodeAuthenticator);
|
|
37
|
+
/**
|
|
38
|
+
* Serialize an ACL to JSON, sign it, and store as a block.
|
|
39
|
+
* Returns the block ID (SHA-256 hex of the stored content).
|
|
40
|
+
*/
|
|
41
|
+
storeACL(acl: IPoolACL<string>, signerPrivateKey: Uint8Array): Promise<string>;
|
|
42
|
+
/**
|
|
43
|
+
* Load an ACL from a stored block, verifying the signature.
|
|
44
|
+
* Throws if the block doesn't exist or the signature is invalid.
|
|
45
|
+
*/
|
|
46
|
+
loadACL(blockId: string): Promise<IPoolACL<string>>;
|
|
47
|
+
/**
|
|
48
|
+
* Update an ACL: sets previousAclBlockId to the current block ID,
|
|
49
|
+
* increments version, and stores the new ACL block.
|
|
50
|
+
*/
|
|
51
|
+
updateACL(currentBlockId: string, updatedAcl: IPoolACL<string>, signerPrivateKey: Uint8Array): Promise<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Store an ACL with pre-collected approval signatures (no re-signing).
|
|
54
|
+
* Used by PoolACLUpdater for quorum-based updates where multiple admins
|
|
55
|
+
* have already signed the proposal.
|
|
56
|
+
* Returns the block ID (SHA-256 hex of the stored content).
|
|
57
|
+
*/
|
|
58
|
+
storeSignedACL(acl: IPoolACL<string>): string;
|
|
59
|
+
/**
|
|
60
|
+
* Check whether a block exists in the store.
|
|
61
|
+
*/
|
|
62
|
+
hasBlock(blockId: string): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Serialize an ACL to JSON, stripping approvalSignatures.
|
|
65
|
+
* Dates are converted to ISO strings for deterministic serialization.
|
|
66
|
+
*/
|
|
67
|
+
private serializeACL;
|
|
68
|
+
/**
|
|
69
|
+
* Deserialize an ACL from JSON, restoring Date objects.
|
|
70
|
+
*/
|
|
71
|
+
private deserializeACL;
|
|
72
|
+
/**
|
|
73
|
+
* Compute a block ID as the SHA-256 hex digest of the content.
|
|
74
|
+
*/
|
|
75
|
+
private computeBlockId;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=poolAclStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poolAclStore.d.ts","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/auth/poolAclStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAG7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1D;AAED;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,SAAS,CAAC,QAAQ,CAAC,MAAM,2CAAiC;IAC1D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyB;gBAE3C,aAAa,CAAC,EAAE,sBAAsB;IAIlD;;;OAGG;IACG,QAAQ,CACZ,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,EACrB,gBAAgB,EAAE,UAAU,GAC3B,OAAO,CAAC,MAAM,CAAC;IAgClB;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IA0CzD;;;OAGG;IACG,SAAS,CACb,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC5B,gBAAgB,EAAE,UAAU,GAC3B,OAAO,CAAC,MAAM,CAAC;IAoBlB;;;;;OAKG;IACH,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM;IAkB7C;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIlC;;;OAGG;IACH,OAAO,CAAC,YAAY;IAoBpB;;OAEG;IACH,OAAO,CAAC,cAAc;IA2BtB;;OAEG;IACH,OAAO,CAAC,cAAc;CAMvB"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pool ACL Store - stores and retrieves ACLs as signed blocks.
|
|
4
|
+
*
|
|
5
|
+
* Each ACL is serialized to JSON (without approvalSignatures), signed with
|
|
6
|
+
* the admin's ECDSA key, and stored as a block. On retrieval, the signature
|
|
7
|
+
* is verified against the first approval signature's public key.
|
|
8
|
+
*
|
|
9
|
+
* ACL chain: each update references the previous ACL block ID via
|
|
10
|
+
* `previousAclBlockId`, forming an auditable linked list.
|
|
11
|
+
*
|
|
12
|
+
* @see Requirements 11.1, 13.3
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PoolACLStore = void 0;
|
|
16
|
+
const tslib_1 = require("tslib");
|
|
17
|
+
const crypto = tslib_1.__importStar(require("crypto"));
|
|
18
|
+
const ecdsaNodeAuthenticator_1 = require("./ecdsaNodeAuthenticator");
|
|
19
|
+
/**
|
|
20
|
+
* Stores and retrieves Pool ACLs as signed blocks.
|
|
21
|
+
*
|
|
22
|
+
* Uses an in-memory Map for block storage (actual block store integration
|
|
23
|
+
* comes in a later task). Block IDs are SHA-256 hashes of the stored content.
|
|
24
|
+
*/
|
|
25
|
+
class PoolACLStore {
|
|
26
|
+
constructor(authenticator) {
|
|
27
|
+
this.blocks = new Map();
|
|
28
|
+
this.authenticator = authenticator ?? new ecdsaNodeAuthenticator_1.ECDSANodeAuthenticator();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Serialize an ACL to JSON, sign it, and store as a block.
|
|
32
|
+
* Returns the block ID (SHA-256 hex of the stored content).
|
|
33
|
+
*/
|
|
34
|
+
async storeACL(acl, signerPrivateKey) {
|
|
35
|
+
const aclJson = this.serializeACL(acl);
|
|
36
|
+
const aclBytes = new TextEncoder().encode(aclJson);
|
|
37
|
+
const signature = await this.authenticator.signChallenge(aclBytes, signerPrivateKey);
|
|
38
|
+
// Derive the signer's public key and node ID
|
|
39
|
+
const ecdh = crypto.createECDH('secp256k1');
|
|
40
|
+
ecdh.setPrivateKey(Buffer.from(signerPrivateKey));
|
|
41
|
+
const publicKey = new Uint8Array(ecdh.getPublicKey());
|
|
42
|
+
const nodeId = this.authenticator.deriveNodeId(publicKey);
|
|
43
|
+
const signedBlock = {
|
|
44
|
+
aclJson,
|
|
45
|
+
signatures: [
|
|
46
|
+
{
|
|
47
|
+
nodeId,
|
|
48
|
+
signature: Buffer.from(signature).toString('hex'),
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
const blockBytes = new TextEncoder().encode(JSON.stringify(signedBlock));
|
|
53
|
+
const blockId = this.computeBlockId(blockBytes);
|
|
54
|
+
this.blocks.set(blockId, blockBytes);
|
|
55
|
+
return blockId;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Load an ACL from a stored block, verifying the signature.
|
|
59
|
+
* Throws if the block doesn't exist or the signature is invalid.
|
|
60
|
+
*/
|
|
61
|
+
async loadACL(blockId) {
|
|
62
|
+
const blockBytes = this.blocks.get(blockId);
|
|
63
|
+
if (!blockBytes) {
|
|
64
|
+
throw new Error(`ACL block not found: ${blockId}`);
|
|
65
|
+
}
|
|
66
|
+
const signedBlock = JSON.parse(new TextDecoder().decode(blockBytes));
|
|
67
|
+
// Find the signer's public key from the ACL members
|
|
68
|
+
const acl = this.deserializeACL(signedBlock.aclJson);
|
|
69
|
+
if (signedBlock.signatures.length === 0) {
|
|
70
|
+
throw new Error('ACL block has no signatures');
|
|
71
|
+
}
|
|
72
|
+
// Verify the first signature against the signer's public key from ACL members
|
|
73
|
+
const firstSig = signedBlock.signatures[0];
|
|
74
|
+
const signerMember = acl.members.find((m) => typeof m.nodeId === 'string' && m.nodeId === firstSig.nodeId);
|
|
75
|
+
if (!signerMember) {
|
|
76
|
+
throw new Error(`Signer ${firstSig.nodeId} is not a member of the ACL`);
|
|
77
|
+
}
|
|
78
|
+
// We cannot verify without the public key stored somewhere accessible.
|
|
79
|
+
// For now, the signature is stored and the ACL is returned with it
|
|
80
|
+
// attached in approvalSignatures. Full verification requires a public
|
|
81
|
+
// key registry (future task). The signed block format preserves the
|
|
82
|
+
// signature for downstream verification.
|
|
83
|
+
// Reconstruct approvalSignatures from the signed block
|
|
84
|
+
acl.approvalSignatures = signedBlock.signatures.map((s) => ({
|
|
85
|
+
nodeId: s.nodeId,
|
|
86
|
+
signature: new Uint8Array(Buffer.from(s.signature, 'hex')),
|
|
87
|
+
}));
|
|
88
|
+
return acl;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Update an ACL: sets previousAclBlockId to the current block ID,
|
|
92
|
+
* increments version, and stores the new ACL block.
|
|
93
|
+
*/
|
|
94
|
+
async updateACL(currentBlockId, updatedAcl, signerPrivateKey) {
|
|
95
|
+
// Verify the current block exists
|
|
96
|
+
if (!this.blocks.has(currentBlockId)) {
|
|
97
|
+
throw new Error(`Current ACL block not found: ${currentBlockId}`);
|
|
98
|
+
}
|
|
99
|
+
// Load the current ACL to get its version
|
|
100
|
+
const currentAcl = await this.loadACL(currentBlockId);
|
|
101
|
+
// Set chain reference and increment version
|
|
102
|
+
const chainedAcl = {
|
|
103
|
+
...updatedAcl,
|
|
104
|
+
previousAclBlockId: currentBlockId,
|
|
105
|
+
version: currentAcl.version + 1,
|
|
106
|
+
updatedAt: new Date(),
|
|
107
|
+
};
|
|
108
|
+
return this.storeACL(chainedAcl, signerPrivateKey);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Store an ACL with pre-collected approval signatures (no re-signing).
|
|
112
|
+
* Used by PoolACLUpdater for quorum-based updates where multiple admins
|
|
113
|
+
* have already signed the proposal.
|
|
114
|
+
* Returns the block ID (SHA-256 hex of the stored content).
|
|
115
|
+
*/
|
|
116
|
+
storeSignedACL(acl) {
|
|
117
|
+
const aclJson = this.serializeACL(acl);
|
|
118
|
+
const signedBlock = {
|
|
119
|
+
aclJson,
|
|
120
|
+
signatures: acl.approvalSignatures.map((s) => ({
|
|
121
|
+
nodeId: s.nodeId,
|
|
122
|
+
signature: Buffer.from(s.signature).toString('hex'),
|
|
123
|
+
})),
|
|
124
|
+
};
|
|
125
|
+
const blockBytes = new TextEncoder().encode(JSON.stringify(signedBlock));
|
|
126
|
+
const blockId = this.computeBlockId(blockBytes);
|
|
127
|
+
this.blocks.set(blockId, blockBytes);
|
|
128
|
+
return blockId;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Check whether a block exists in the store.
|
|
132
|
+
*/
|
|
133
|
+
hasBlock(blockId) {
|
|
134
|
+
return this.blocks.has(blockId);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Serialize an ACL to JSON, stripping approvalSignatures.
|
|
138
|
+
* Dates are converted to ISO strings for deterministic serialization.
|
|
139
|
+
*/
|
|
140
|
+
serializeACL(acl) {
|
|
141
|
+
const { approvalSignatures: _, ...aclWithoutSigs } = acl;
|
|
142
|
+
// Convert Dates to ISO strings for stable JSON
|
|
143
|
+
const serializable = {
|
|
144
|
+
...aclWithoutSigs,
|
|
145
|
+
updatedAt: acl.updatedAt instanceof Date
|
|
146
|
+
? acl.updatedAt.toISOString()
|
|
147
|
+
: acl.updatedAt,
|
|
148
|
+
members: acl.members.map((m) => ({
|
|
149
|
+
...m,
|
|
150
|
+
addedAt: m.addedAt instanceof Date ? m.addedAt.toISOString() : m.addedAt,
|
|
151
|
+
})),
|
|
152
|
+
};
|
|
153
|
+
return JSON.stringify(serializable);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Deserialize an ACL from JSON, restoring Date objects.
|
|
157
|
+
*/
|
|
158
|
+
deserializeACL(json) {
|
|
159
|
+
const raw = JSON.parse(json);
|
|
160
|
+
const members = raw['members'].map((m) => ({
|
|
161
|
+
nodeId: m['nodeId'],
|
|
162
|
+
permissions: m['permissions'],
|
|
163
|
+
addedAt: new Date(m['addedAt']),
|
|
164
|
+
addedBy: m['addedBy'],
|
|
165
|
+
}));
|
|
166
|
+
return {
|
|
167
|
+
poolId: raw['poolId'],
|
|
168
|
+
owner: raw['owner'],
|
|
169
|
+
members,
|
|
170
|
+
publicRead: raw['publicRead'],
|
|
171
|
+
publicWrite: raw['publicWrite'],
|
|
172
|
+
previousAclBlockId: raw['previousAclBlockId'],
|
|
173
|
+
approvalSignatures: [],
|
|
174
|
+
version: raw['version'],
|
|
175
|
+
updatedAt: new Date(raw['updatedAt']),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Compute a block ID as the SHA-256 hex digest of the content.
|
|
180
|
+
*/
|
|
181
|
+
computeBlockId(content) {
|
|
182
|
+
return crypto
|
|
183
|
+
.createHash('sha256')
|
|
184
|
+
.update(Buffer.from(content))
|
|
185
|
+
.digest('hex');
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
exports.PoolACLStore = PoolACLStore;
|
|
189
|
+
//# sourceMappingURL=poolAclStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poolAclStore.js","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/auth/poolAclStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pool ACL Updater - quorum-based ACL update workflow.
|
|
3
|
+
*
|
|
4
|
+
* Provides a propose → collect signatures → apply workflow for ACL changes.
|
|
5
|
+
* Uses `hasQuorum()` from brightchain-lib to verify majority approval.
|
|
6
|
+
*
|
|
7
|
+
* @see Requirements 13.1, 13.2, 13.5, 13.6
|
|
8
|
+
*/
|
|
9
|
+
import type { IPoolACL } from '@brightchain/brightchain-lib';
|
|
10
|
+
import { ECDSANodeAuthenticator } from './ecdsaNodeAuthenticator';
|
|
11
|
+
import { PoolACLStore } from './poolAclStore';
|
|
12
|
+
/**
|
|
13
|
+
* Error thrown when an ACL update would remove the last Admin.
|
|
14
|
+
* @see Requirement 13.6
|
|
15
|
+
*/
|
|
16
|
+
export declare class LastAdminError extends Error {
|
|
17
|
+
constructor();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Error thrown when an ACL update does not have sufficient signatures.
|
|
21
|
+
* @see Requirement 13.5
|
|
22
|
+
*/
|
|
23
|
+
export declare class InsufficientQuorumError extends Error {
|
|
24
|
+
readonly required: number;
|
|
25
|
+
readonly actual: number;
|
|
26
|
+
constructor(required: number, actual: number);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A proposal for an ACL update that collects admin signatures.
|
|
30
|
+
*/
|
|
31
|
+
export interface ACLUpdateProposal {
|
|
32
|
+
currentBlockId: string;
|
|
33
|
+
proposedAcl: IPoolACL<string>;
|
|
34
|
+
signatures: Array<{
|
|
35
|
+
nodeId: string;
|
|
36
|
+
signature: Uint8Array;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
39
|
+
export declare class PoolACLUpdater {
|
|
40
|
+
private readonly store;
|
|
41
|
+
private readonly authenticator;
|
|
42
|
+
constructor(store: PoolACLStore, authenticator?: ECDSANodeAuthenticator);
|
|
43
|
+
/**
|
|
44
|
+
* Propose an ACL update. Validates that at least one Admin remains.
|
|
45
|
+
* Returns a proposal object that can collect signatures before applying.
|
|
46
|
+
*
|
|
47
|
+
* @see Requirements 13.1, 13.6
|
|
48
|
+
*/
|
|
49
|
+
proposeUpdate(currentBlockId: string, proposedAcl: IPoolACL<string>): Promise<ACLUpdateProposal>;
|
|
50
|
+
/**
|
|
51
|
+
* Sign a proposal with an admin's private key and add the signature.
|
|
52
|
+
* Derives the node ID from the private key and signs the serialized
|
|
53
|
+
* proposed ACL.
|
|
54
|
+
*
|
|
55
|
+
* @see Requirement 13.1
|
|
56
|
+
*/
|
|
57
|
+
addSignature(proposal: ACLUpdateProposal, signerPrivateKey: Uint8Array): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Apply a proposed ACL update if quorum is met.
|
|
60
|
+
* Attaches collected signatures to the ACL, checks quorum via
|
|
61
|
+
* `hasQuorum()`, and stores the updated ACL via `PoolACLStore.updateACL()`.
|
|
62
|
+
*
|
|
63
|
+
* @returns The new ACL block ID
|
|
64
|
+
* @throws InsufficientQuorumError if quorum is not met
|
|
65
|
+
* @see Requirements 13.1, 13.2, 13.5
|
|
66
|
+
*/
|
|
67
|
+
applyUpdate(proposal: ACLUpdateProposal): Promise<string>;
|
|
68
|
+
/**
|
|
69
|
+
* Validate that the proposed ACL has at least one Admin member.
|
|
70
|
+
* @throws LastAdminError if no Admin members remain
|
|
71
|
+
* @see Requirement 13.6
|
|
72
|
+
*/
|
|
73
|
+
validateMinAdmin(acl: IPoolACL<string>): void;
|
|
74
|
+
/**
|
|
75
|
+
* Serialize an ACL for signing (deterministic JSON without signatures).
|
|
76
|
+
*/
|
|
77
|
+
private serializeForSigning;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=poolAclUpdater.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poolAclUpdater.d.ts","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/auth/poolAclUpdater.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAI7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;GAGG;AACH,qBAAa,cAAe,SAAQ,KAAK;;CAKxC;AAED;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,MAAM,EAAE,MAAM,CAAC;gBAEnB,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAQ7C;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9B,UAAU,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;CAC9D;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyB;gBAE3C,KAAK,EAAE,YAAY,EAAE,aAAa,CAAC,EAAE,sBAAsB;IAKvE;;;;;OAKG;IACG,aAAa,CACjB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,GAC5B,OAAO,CAAC,iBAAiB,CAAC;IAU7B;;;;;;OAMG;IACG,YAAY,CAChB,QAAQ,EAAE,iBAAiB,EAC3B,gBAAgB,EAAE,UAAU,GAC3B,OAAO,CAAC,IAAI,CAAC;IAkBhB;;;;;;;;OAQG;IACG,WAAW,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAoC/D;;;;OAIG;IACH,gBAAgB,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI;IAS7C;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAgB5B"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pool ACL Updater - quorum-based ACL update workflow.
|
|
4
|
+
*
|
|
5
|
+
* Provides a propose → collect signatures → apply workflow for ACL changes.
|
|
6
|
+
* Uses `hasQuorum()` from brightchain-lib to verify majority approval.
|
|
7
|
+
*
|
|
8
|
+
* @see Requirements 13.1, 13.2, 13.5, 13.6
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.PoolACLUpdater = exports.InsufficientQuorumError = exports.LastAdminError = void 0;
|
|
12
|
+
const tslib_1 = require("tslib");
|
|
13
|
+
const brightchain_lib_1 = require("@brightchain/brightchain-lib");
|
|
14
|
+
const crypto = tslib_1.__importStar(require("crypto"));
|
|
15
|
+
const ecdsaNodeAuthenticator_1 = require("./ecdsaNodeAuthenticator");
|
|
16
|
+
/**
|
|
17
|
+
* Error thrown when an ACL update would remove the last Admin.
|
|
18
|
+
* @see Requirement 13.6
|
|
19
|
+
*/
|
|
20
|
+
class LastAdminError extends Error {
|
|
21
|
+
constructor() {
|
|
22
|
+
super('Cannot remove the last Admin from the ACL');
|
|
23
|
+
this.name = 'LastAdminError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.LastAdminError = LastAdminError;
|
|
27
|
+
/**
|
|
28
|
+
* Error thrown when an ACL update does not have sufficient signatures.
|
|
29
|
+
* @see Requirement 13.5
|
|
30
|
+
*/
|
|
31
|
+
class InsufficientQuorumError extends Error {
|
|
32
|
+
constructor(required, actual) {
|
|
33
|
+
super(`Insufficient quorum: ${actual} signature(s) provided, more than ${required} required`);
|
|
34
|
+
this.name = 'InsufficientQuorumError';
|
|
35
|
+
this.required = required;
|
|
36
|
+
this.actual = actual;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.InsufficientQuorumError = InsufficientQuorumError;
|
|
40
|
+
class PoolACLUpdater {
|
|
41
|
+
constructor(store, authenticator) {
|
|
42
|
+
this.store = store;
|
|
43
|
+
this.authenticator = authenticator ?? new ecdsaNodeAuthenticator_1.ECDSANodeAuthenticator();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Propose an ACL update. Validates that at least one Admin remains.
|
|
47
|
+
* Returns a proposal object that can collect signatures before applying.
|
|
48
|
+
*
|
|
49
|
+
* @see Requirements 13.1, 13.6
|
|
50
|
+
*/
|
|
51
|
+
async proposeUpdate(currentBlockId, proposedAcl) {
|
|
52
|
+
this.validateMinAdmin(proposedAcl);
|
|
53
|
+
return {
|
|
54
|
+
currentBlockId,
|
|
55
|
+
proposedAcl,
|
|
56
|
+
signatures: [],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Sign a proposal with an admin's private key and add the signature.
|
|
61
|
+
* Derives the node ID from the private key and signs the serialized
|
|
62
|
+
* proposed ACL.
|
|
63
|
+
*
|
|
64
|
+
* @see Requirement 13.1
|
|
65
|
+
*/
|
|
66
|
+
async addSignature(proposal, signerPrivateKey) {
|
|
67
|
+
const ecdh = crypto.createECDH('secp256k1');
|
|
68
|
+
ecdh.setPrivateKey(Buffer.from(signerPrivateKey));
|
|
69
|
+
const publicKey = new Uint8Array(ecdh.getPublicKey());
|
|
70
|
+
const nodeId = this.authenticator.deriveNodeId(publicKey);
|
|
71
|
+
// Sign the serialized proposed ACL (without signatures)
|
|
72
|
+
const aclBytes = new TextEncoder().encode(this.serializeForSigning(proposal.proposedAcl));
|
|
73
|
+
const signature = await this.authenticator.signChallenge(aclBytes, signerPrivateKey);
|
|
74
|
+
proposal.signatures.push({ nodeId, signature });
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Apply a proposed ACL update if quorum is met.
|
|
78
|
+
* Attaches collected signatures to the ACL, checks quorum via
|
|
79
|
+
* `hasQuorum()`, and stores the updated ACL via `PoolACLStore.updateACL()`.
|
|
80
|
+
*
|
|
81
|
+
* @returns The new ACL block ID
|
|
82
|
+
* @throws InsufficientQuorumError if quorum is not met
|
|
83
|
+
* @see Requirements 13.1, 13.2, 13.5
|
|
84
|
+
*/
|
|
85
|
+
async applyUpdate(proposal) {
|
|
86
|
+
// Load current ACL to check quorum against current admin count
|
|
87
|
+
const currentAcl = await this.store.loadACL(proposal.currentBlockId);
|
|
88
|
+
// Build a quorum-check ACL using current members + collected signatures
|
|
89
|
+
const quorumCheckAcl = {
|
|
90
|
+
...currentAcl,
|
|
91
|
+
approvalSignatures: proposal.signatures.map((s) => ({
|
|
92
|
+
nodeId: s.nodeId,
|
|
93
|
+
signature: s.signature,
|
|
94
|
+
})),
|
|
95
|
+
};
|
|
96
|
+
if (!(0, brightchain_lib_1.hasQuorum)(quorumCheckAcl)) {
|
|
97
|
+
const adminCount = currentAcl.members.filter((m) => m.permissions.includes(brightchain_lib_1.PoolPermission.Admin)).length;
|
|
98
|
+
const required = Math.floor(adminCount / 2);
|
|
99
|
+
throw new InsufficientQuorumError(required, proposal.signatures.length);
|
|
100
|
+
}
|
|
101
|
+
// Attach collected signatures to the proposed ACL
|
|
102
|
+
const chainedAcl = {
|
|
103
|
+
...proposal.proposedAcl,
|
|
104
|
+
approvalSignatures: proposal.signatures.map((s) => ({
|
|
105
|
+
nodeId: s.nodeId,
|
|
106
|
+
signature: s.signature,
|
|
107
|
+
})),
|
|
108
|
+
previousAclBlockId: proposal.currentBlockId,
|
|
109
|
+
version: currentAcl.version + 1,
|
|
110
|
+
updatedAt: new Date(),
|
|
111
|
+
};
|
|
112
|
+
return this.store.storeSignedACL(chainedAcl);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Validate that the proposed ACL has at least one Admin member.
|
|
116
|
+
* @throws LastAdminError if no Admin members remain
|
|
117
|
+
* @see Requirement 13.6
|
|
118
|
+
*/
|
|
119
|
+
validateMinAdmin(acl) {
|
|
120
|
+
const adminCount = acl.members.filter((m) => m.permissions.includes(brightchain_lib_1.PoolPermission.Admin)).length;
|
|
121
|
+
if (adminCount === 0) {
|
|
122
|
+
throw new LastAdminError();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Serialize an ACL for signing (deterministic JSON without signatures).
|
|
127
|
+
*/
|
|
128
|
+
serializeForSigning(acl) {
|
|
129
|
+
const { approvalSignatures: _, ...aclWithoutSigs } = acl;
|
|
130
|
+
const serializable = {
|
|
131
|
+
...aclWithoutSigs,
|
|
132
|
+
updatedAt: acl.updatedAt instanceof Date
|
|
133
|
+
? acl.updatedAt.toISOString()
|
|
134
|
+
: acl.updatedAt,
|
|
135
|
+
members: acl.members.map((m) => ({
|
|
136
|
+
...m,
|
|
137
|
+
addedAt: m.addedAt instanceof Date ? m.addedAt.toISOString() : m.addedAt,
|
|
138
|
+
})),
|
|
139
|
+
};
|
|
140
|
+
return JSON.stringify(serializable);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.PoolACLUpdater = PoolACLUpdater;
|
|
144
|
+
//# sourceMappingURL=poolAclUpdater.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poolAclUpdater.js","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/auth/poolAclUpdater.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @see Requirements 1.7, 7.2, 7.3, 7.4, 7.5, 7.7, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 14.1, 14.2, 14.3, 14.4, 14.5, 14.6
|
|
9
9
|
*/
|
|
10
|
-
import { AvailabilityEventHandler, AvailabilityServiceConfig, AvailabilityState, AvailabilityStatistics, EventFilter, IAvailabilityService, IBlockRegistry, IDiscoveryProtocol, IGossipService, IHeartbeatMonitor, ILocationRecord, IReconciliationService, LocationQueryResult, ReconciliationResult } from '@brightchain/brightchain-lib';
|
|
10
|
+
import { AvailabilityEventHandler, AvailabilityServiceConfig, AvailabilityState, AvailabilityStatistics, EventFilter, IAvailabilityService, IBlockRegistry, IDiscoveryProtocol, IGossipService, IHeartbeatMonitor, ILocationRecord, IReconciliationService, LocationQueryResult, PoolId, ReconciliationResult } from '@brightchain/brightchain-lib';
|
|
11
11
|
/**
|
|
12
12
|
* Internal structure for tracking block metadata with location.
|
|
13
13
|
*/
|
|
@@ -86,7 +86,7 @@ export declare class AvailabilityService implements IAvailabilityService {
|
|
|
86
86
|
* @returns Promise resolving to array of location records
|
|
87
87
|
* @see Requirements 11.2
|
|
88
88
|
*/
|
|
89
|
-
getBlockLocations(blockId: string): Promise<ILocationRecord[]>;
|
|
89
|
+
getBlockLocations(blockId: string, poolId?: PoolId): Promise<ILocationRecord[]>;
|
|
90
90
|
/**
|
|
91
91
|
* Get detailed location query result with staleness indication.
|
|
92
92
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"availabilityService.d.ts","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/availability/availabilityService.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAEL,wBAAwB,EACxB,yBAAyB,EACzB,iBAAiB,EACjB,sBAAsB,EAEtB,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AAEtC;;GAEG;AACH,UAAU,iBAAiB;IACzB;;OAEG;IACH,KAAK,EAAE,iBAAiB,CAAC;IAEzB;;OAEG;IACH,SAAS,EAAE,eAAe,EAAE,CAAC;IAE7B;;OAEG;IACH,WAAW,EAAE,IAAI,CAAC;CACnB;AAUD;;;;;;;GAOG;AACH,qBAAa,mBAAoB,YAAW,oBAAoB;IAqC5D,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAzCzB;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6C;IAEvE;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAEhE;;OAEG;IACH,OAAO,CAAC,aAAa,CAAS;IAE9B;;OAEG;IACH,OAAO,CAAC,iBAAiB,CAAgB;IAEzC;;OAEG;IACH,OAAO,CAAC,OAAO,CAAS;IAExB;;;;;;;;;OASG;gBAEgB,QAAQ,EAAE,cAAc,EACxB,iBAAiB,EAAE,kBAAkB,EACrC,aAAa,EAAE,cAAc,EAC7B,qBAAqB,EAAE,sBAAsB,EAC7C,gBAAgB,EAAE,iBAAiB,EACnC,MAAM,GAAE,yBAA+D;IAU1F;;;;;;OAMG;IACG,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAgBvE;;;;;;OAMG;IACG,iBAAiB,
|
|
1
|
+
{"version":3,"file":"availabilityService.d.ts","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/availability/availabilityService.ts"],"names":[],"mappings":"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"}
|
|
@@ -90,10 +90,14 @@ class AvailabilityService {
|
|
|
90
90
|
* @returns Promise resolving to array of location records
|
|
91
91
|
* @see Requirements 11.2
|
|
92
92
|
*/
|
|
93
|
-
async getBlockLocations(blockId) {
|
|
93
|
+
async getBlockLocations(blockId, poolId) {
|
|
94
94
|
const data = this.blockData.get(blockId);
|
|
95
95
|
if (data) {
|
|
96
|
-
|
|
96
|
+
const locations = [...data.locations];
|
|
97
|
+
if (poolId !== undefined) {
|
|
98
|
+
return locations.filter((l) => l.poolId === poolId);
|
|
99
|
+
}
|
|
100
|
+
return locations;
|
|
97
101
|
}
|
|
98
102
|
// If local, return local node as location
|
|
99
103
|
if (this.registry.hasLocal(blockId)) {
|
|
@@ -209,7 +213,10 @@ class AvailabilityService {
|
|
|
209
213
|
*/
|
|
210
214
|
async updateLocation(blockId, location) {
|
|
211
215
|
let data = this.blockData.get(blockId);
|
|
212
|
-
|
|
216
|
+
// Use (nodeId, poolId) as composite key for deduplication.
|
|
217
|
+
// When poolId is undefined, fall back to nodeId-only matching for backward compatibility.
|
|
218
|
+
const matchesCompositeKey = (l) => l.nodeId === location.nodeId && l.poolId === location.poolId;
|
|
219
|
+
const isNewLocation = !data || !data.locations.some(matchesCompositeKey);
|
|
213
220
|
if (!data) {
|
|
214
221
|
// Determine initial state based on location
|
|
215
222
|
const state = location.nodeId === this.config.localNodeId
|
|
@@ -222,8 +229,8 @@ class AvailabilityService {
|
|
|
222
229
|
};
|
|
223
230
|
this.blockData.set(blockId, data);
|
|
224
231
|
}
|
|
225
|
-
// Update or add location
|
|
226
|
-
const existingIndex = data.locations.findIndex(
|
|
232
|
+
// Update or add location using composite key (nodeId, poolId)
|
|
233
|
+
const existingIndex = data.locations.findIndex(matchesCompositeKey);
|
|
227
234
|
if (existingIndex >= 0) {
|
|
228
235
|
data.locations[existingIndex] = { ...location };
|
|
229
236
|
}
|