@brightchain/brightchain-api-lib 0.18.2 → 0.21.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 +8 -3
- package/src/index.d.ts +0 -1
- package/src/index.d.ts.map +1 -1
- package/src/index.js +0 -1
- package/src/index.js.map +1 -1
- package/src/lib/application.d.ts +12 -3
- package/src/lib/application.d.ts.map +1 -1
- package/src/lib/application.js +153 -7
- package/src/lib/application.js.map +1 -1
- package/src/lib/availability/gossipService.d.ts +59 -1
- package/src/lib/availability/gossipService.d.ts.map +1 -1
- package/src/lib/availability/gossipService.js +125 -1
- package/src/lib/availability/gossipService.js.map +1 -1
- package/src/lib/availability/index.d.ts +1 -0
- package/src/lib/availability/index.d.ts.map +1 -1
- package/src/lib/availability/index.js +1 -0
- package/src/lib/availability/index.js.map +1 -1
- package/src/lib/availability/quorumGossipHandler.d.ts +126 -0
- package/src/lib/availability/quorumGossipHandler.d.ts.map +1 -0
- package/src/lib/availability/quorumGossipHandler.js +246 -0
- package/src/lib/availability/quorumGossipHandler.js.map +1 -0
- package/src/lib/constants.d.ts.map +1 -1
- package/src/lib/constants.js +4 -0
- package/src/lib/constants.js.map +1 -1
- package/src/lib/controllers/api/quorum.d.ts +110 -2
- package/src/lib/controllers/api/quorum.d.ts.map +1 -1
- package/src/lib/controllers/api/quorum.js +389 -0
- package/src/lib/controllers/api/quorum.js.map +1 -1
- package/src/lib/controllers/api/user.d.ts +12 -15
- package/src/lib/controllers/api/user.d.ts.map +1 -1
- package/src/lib/controllers/api/user.js +312 -94
- package/src/lib/controllers/api/user.js.map +1 -1
- package/src/lib/databaseInit.d.ts +3 -2
- package/src/lib/databaseInit.d.ts.map +1 -1
- package/src/lib/databaseInit.js +24 -12
- package/src/lib/databaseInit.js.map +1 -1
- package/src/lib/datastore/index.d.ts +0 -1
- package/src/lib/datastore/index.d.ts.map +1 -1
- package/src/lib/datastore/index.js +0 -1
- package/src/lib/datastore/index.js.map +1 -1
- package/src/lib/environment.d.ts +6 -0
- package/src/lib/environment.d.ts.map +1 -1
- package/src/lib/environment.js +14 -0
- package/src/lib/environment.js.map +1 -1
- package/src/lib/hydration/energyAccountHydration.d.ts +17 -0
- package/src/lib/hydration/energyAccountHydration.d.ts.map +1 -0
- package/src/lib/hydration/energyAccountHydration.js +24 -0
- package/src/lib/hydration/energyAccountHydration.js.map +1 -0
- package/src/lib/hydration/index.d.ts +13 -0
- package/src/lib/hydration/index.d.ts.map +1 -0
- package/src/lib/hydration/index.js +21 -0
- package/src/lib/hydration/index.js.map +1 -0
- package/src/lib/hydration/rbacHydration.d.ts +28 -0
- package/src/lib/hydration/rbacHydration.d.ts.map +1 -0
- package/src/lib/hydration/rbacHydration.js +56 -0
- package/src/lib/hydration/rbacHydration.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/responses/api-backup-codes-response.d.ts +1 -1
- package/src/lib/interfaces/responses/api-code-count-response.d.ts +1 -1
- package/src/lib/interfaces/responses/api-password-change-response.d.ts +9 -0
- package/src/lib/interfaces/responses/api-password-change-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-password-change-response.js +3 -0
- package/src/lib/interfaces/responses/api-password-change-response.js.map +1 -0
- package/src/lib/interfaces/responses/api-recovery-response.d.ts +9 -0
- package/src/lib/interfaces/responses/api-recovery-response.d.ts.map +1 -0
- package/src/lib/interfaces/responses/api-recovery-response.js +3 -0
- package/src/lib/interfaces/responses/api-recovery-response.js.map +1 -0
- package/src/lib/interfaces/responses/index.d.ts +2 -0
- package/src/lib/interfaces/responses/index.d.ts.map +1 -1
- package/src/lib/interfaces/storage/client-session.d.ts +1 -1
- package/src/lib/interfaces/storage/client-session.d.ts.map +1 -1
- package/src/lib/interfaces/storage/collection.d.ts +1 -1
- package/src/lib/interfaces/storage/collection.d.ts.map +1 -1
- package/src/lib/interfaces/storage/database-lifecycle-hooks.d.ts +1 -1
- package/src/lib/interfaces/storage/database-lifecycle-hooks.d.ts.map +1 -1
- package/src/lib/interfaces/storage/database.d.ts +1 -1
- package/src/lib/interfaces/storage/database.d.ts.map +1 -1
- package/src/lib/interfaces/storage/document-types.d.ts +1 -1
- package/src/lib/interfaces/storage/document-types.d.ts.map +1 -1
- package/src/lib/interfaces/storage/index.d.ts +1 -0
- package/src/lib/interfaces/storage/index.d.ts.map +1 -1
- package/src/lib/interfaces/storage/index.js.map +1 -1
- package/src/lib/interfaces/storage/storedDocumentTypes.d.ts +73 -0
- package/src/lib/interfaces/storage/storedDocumentTypes.d.ts.map +1 -0
- package/src/lib/interfaces/storage/storedDocumentTypes.js +15 -0
- package/src/lib/interfaces/storage/storedDocumentTypes.js.map +1 -0
- package/src/lib/plugins/brightchain-database-plugin.d.ts +31 -21
- package/src/lib/plugins/brightchain-database-plugin.d.ts.map +1 -1
- package/src/lib/plugins/brightchain-database-plugin.js +103 -53
- package/src/lib/plugins/brightchain-database-plugin.js.map +1 -1
- package/src/lib/plugins/configure-brightchain-app.d.ts.map +1 -1
- package/src/lib/plugins/configure-brightchain-app.js +5 -0
- package/src/lib/plugins/configure-brightchain-app.js.map +1 -1
- package/src/lib/services/auth.d.ts +6 -2
- package/src/lib/services/auth.d.ts.map +1 -1
- package/src/lib/services/auth.js +43 -7
- package/src/lib/services/auth.js.map +1 -1
- package/src/lib/services/backupCodeService.d.ts +35 -0
- package/src/lib/services/backupCodeService.d.ts.map +1 -0
- package/src/lib/services/backupCodeService.js +109 -0
- package/src/lib/services/backupCodeService.js.map +1 -0
- package/src/lib/services/brightchain-authentication-provider.d.ts.map +1 -1
- package/src/lib/services/brightchain-authentication-provider.js +28 -9
- package/src/lib/services/brightchain-authentication-provider.js.map +1 -1
- package/src/lib/services/brightchain-member-init.service.d.ts +39 -20
- package/src/lib/services/brightchain-member-init.service.d.ts.map +1 -1
- package/src/lib/services/brightchain-member-init.service.js +139 -53
- package/src/lib/services/brightchain-member-init.service.js.map +1 -1
- package/src/lib/services/cliOperatorPrompt.d.ts +81 -0
- package/src/lib/services/cliOperatorPrompt.d.ts.map +1 -0
- package/src/lib/services/cliOperatorPrompt.js +177 -0
- package/src/lib/services/cliOperatorPrompt.js.map +1 -0
- package/src/lib/services/contentAwareBlocksService.d.ts +92 -0
- package/src/lib/services/contentAwareBlocksService.d.ts.map +1 -0
- package/src/lib/services/contentAwareBlocksService.js +102 -0
- package/src/lib/services/contentAwareBlocksService.js.map +1 -0
- package/src/lib/services/contentIngestionService.d.ts +68 -0
- package/src/lib/services/contentIngestionService.d.ts.map +1 -0
- package/src/lib/services/contentIngestionService.js +139 -0
- package/src/lib/services/contentIngestionService.js.map +1 -0
- package/src/lib/services/identityExpirationScheduler.d.ts +77 -0
- package/src/lib/services/identityExpirationScheduler.d.ts.map +1 -0
- package/src/lib/services/identityExpirationScheduler.js +157 -0
- package/src/lib/services/identityExpirationScheduler.js.map +1 -0
- package/src/lib/services/index.d.ts +7 -0
- package/src/lib/services/index.d.ts.map +1 -1
- package/src/lib/services/index.js +7 -0
- package/src/lib/services/index.js.map +1 -1
- package/src/lib/services/quorumDatabaseAdapter.d.ts +60 -0
- package/src/lib/services/quorumDatabaseAdapter.d.ts.map +1 -0
- package/src/lib/services/quorumDatabaseAdapter.js +652 -0
- package/src/lib/services/quorumDatabaseAdapter.js.map +1 -0
- package/src/lib/services/secureKeyStorage.js +3 -3
- package/src/lib/services/secureKeyStorage.js.map +1 -1
- package/src/lib/services/sessionAdapter.d.ts +62 -0
- package/src/lib/services/sessionAdapter.d.ts.map +1 -0
- package/src/lib/services/sessionAdapter.js +105 -0
- package/src/lib/services/sessionAdapter.js.map +1 -0
- package/src/lib/utils/rehydration.d.ts +31 -0
- package/src/lib/utils/rehydration.d.ts.map +1 -0
- package/src/lib/utils/rehydration.js +111 -0
- package/src/lib/utils/rehydration.js.map +1 -0
- package/src/lib/utils/serialization.d.ts +21 -0
- package/src/lib/utils/serialization.d.ts.map +1 -0
- package/src/lib/utils/serialization.js +41 -0
- package/src/lib/utils/serialization.js.map +1 -0
- package/src/lib/validation/userValidation.d.ts +17 -0
- package/src/lib/validation/userValidation.d.ts.map +1 -1
- package/src/lib/validation/userValidation.js +77 -0
- package/src/lib/validation/userValidation.js.map +1 -1
- package/src/lib/adapters/brightChainDbDocumentStoreAdapter.d.ts +0 -24
- package/src/lib/adapters/brightChainDbDocumentStoreAdapter.d.ts.map +0 -1
- package/src/lib/adapters/brightChainDbDocumentStoreAdapter.js +0 -53
- package/src/lib/adapters/brightChainDbDocumentStoreAdapter.js.map +0 -1
- package/src/lib/datastore/document-model-adapter.d.ts +0 -48
- package/src/lib/datastore/document-model-adapter.d.ts.map +0 -1
- package/src/lib/datastore/document-model-adapter.js +0 -178
- package/src/lib/datastore/document-model-adapter.js.map +0 -1
- /package/{brightchain-api-lib/README.md → README.md} +0 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CLIOperatorPrompt — Node.js readline-based implementation of IOperatorPrompt.
|
|
4
|
+
*
|
|
5
|
+
* Presents quorum proposals to the node operator via the terminal and collects
|
|
6
|
+
* vote decisions with password authentication on approve votes.
|
|
7
|
+
*
|
|
8
|
+
* Tracks failed authentication attempts per proposal and locks voting after
|
|
9
|
+
* a configurable number of consecutive failures for a cooldown period.
|
|
10
|
+
*
|
|
11
|
+
* This is a Node.js-specific service that lives in brightchain-api-lib.
|
|
12
|
+
*
|
|
13
|
+
* @see Requirements 6
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.CLIOperatorPrompt = void 0;
|
|
17
|
+
const tslib_1 = require("tslib");
|
|
18
|
+
const readline = tslib_1.__importStar(require("readline"));
|
|
19
|
+
// ─── Default Config ─────────────────────────────────────────────────────────
|
|
20
|
+
const DEFAULT_CONFIG = {
|
|
21
|
+
maxAttempts: 3,
|
|
22
|
+
cooldownMs: 300000, // 5 minutes
|
|
23
|
+
};
|
|
24
|
+
// ─── Implementation ─────────────────────────────────────────────────────────
|
|
25
|
+
/**
|
|
26
|
+
* CLI-based operator prompt for quorum voting.
|
|
27
|
+
*
|
|
28
|
+
* Uses Node.js readline to interact with the operator via stdin/stdout.
|
|
29
|
+
* Tracks failed authentication attempts per proposal and enforces lockout
|
|
30
|
+
* after the configured maximum failures.
|
|
31
|
+
*/
|
|
32
|
+
class CLIOperatorPrompt {
|
|
33
|
+
constructor(config, rlFactory, output) {
|
|
34
|
+
this.lockoutMap = new Map();
|
|
35
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
36
|
+
this.output = output ?? process.stdout;
|
|
37
|
+
this.rlFactory =
|
|
38
|
+
rlFactory ??
|
|
39
|
+
(() => readline.createInterface({
|
|
40
|
+
input: process.stdin,
|
|
41
|
+
output: this.output,
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if the voting interface is locked for a given proposal.
|
|
46
|
+
* Returns true if the operator has exceeded the maximum failed attempts
|
|
47
|
+
* and the cooldown period has not yet elapsed.
|
|
48
|
+
*/
|
|
49
|
+
isLocked(proposalId) {
|
|
50
|
+
const state = this.lockoutMap.get(proposalId);
|
|
51
|
+
if (!state || state.lockedAt === null) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const elapsed = Date.now() - state.lockedAt;
|
|
55
|
+
if (elapsed >= this.config.cooldownMs) {
|
|
56
|
+
// Cooldown expired — reset lockout state
|
|
57
|
+
state.failedAttempts = 0;
|
|
58
|
+
state.lockedAt = null;
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Present a proposal to the operator and collect their vote.
|
|
65
|
+
* Displays proposal details, collects a vote decision, and on approve
|
|
66
|
+
* requires password authentication.
|
|
67
|
+
*
|
|
68
|
+
* @throws Error if the proposal is currently locked due to failed attempts
|
|
69
|
+
*/
|
|
70
|
+
async promptForVote(proposal) {
|
|
71
|
+
if (this.isLocked(proposal.proposalId)) {
|
|
72
|
+
throw new Error(`Voting is locked for proposal ${proposal.proposalId}. Please wait for the cooldown period to expire.`);
|
|
73
|
+
}
|
|
74
|
+
const rl = this.rlFactory();
|
|
75
|
+
try {
|
|
76
|
+
this.displayProposal(proposal);
|
|
77
|
+
const decision = await this.collectDecision(rl);
|
|
78
|
+
if (decision === 'reject') {
|
|
79
|
+
return { decision: 'reject' };
|
|
80
|
+
}
|
|
81
|
+
// Approve path — collect password
|
|
82
|
+
const password = await this.collectPassword(rl);
|
|
83
|
+
if (!password) {
|
|
84
|
+
this.recordFailedAttempt(proposal.proposalId);
|
|
85
|
+
throw new Error('Authentication failed: empty password provided.');
|
|
86
|
+
}
|
|
87
|
+
// Reset failed attempts on successful authentication
|
|
88
|
+
this.resetAttempts(proposal.proposalId);
|
|
89
|
+
return { decision: 'approve', password };
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
rl.close();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// ─── Private Helpers ────────────────────────────────────────────────────
|
|
96
|
+
/**
|
|
97
|
+
* Display proposal details to the operator via the readline output.
|
|
98
|
+
*/
|
|
99
|
+
displayProposal(proposal) {
|
|
100
|
+
this.output.write('\n══════════════════════════════════════════════════\n');
|
|
101
|
+
this.output.write(' QUORUM PROPOSAL — VOTE REQUIRED\n');
|
|
102
|
+
this.output.write('══════════════════════════════════════════════════\n\n');
|
|
103
|
+
this.output.write(` Proposal ID: ${proposal.proposalId}\n`);
|
|
104
|
+
this.output.write(` Description: ${proposal.description}\n`);
|
|
105
|
+
this.output.write(` Action Type: ${proposal.actionType}\n`);
|
|
106
|
+
this.output.write(` Action Payload: ${JSON.stringify(proposal.actionPayload, null, 2)}\n`);
|
|
107
|
+
this.output.write(` Proposer: ${proposal.proposerMemberId}\n`);
|
|
108
|
+
this.output.write(` Expires At: ${proposal.expiresAt.toISOString()}\n`);
|
|
109
|
+
if (proposal.attachmentCblId) {
|
|
110
|
+
this.output.write(` Attachment: CBL ${proposal.attachmentCblId}\n`);
|
|
111
|
+
}
|
|
112
|
+
if (proposal.attachmentContent) {
|
|
113
|
+
this.output.write(` Attachment Size: ${proposal.attachmentContent.byteLength} bytes\n`);
|
|
114
|
+
}
|
|
115
|
+
this.output.write('\n──────────────────────────────────────────────────\n');
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Prompt the operator for their vote decision (approve or reject).
|
|
119
|
+
*/
|
|
120
|
+
collectDecision(rl) {
|
|
121
|
+
return new Promise((resolve) => {
|
|
122
|
+
const ask = () => {
|
|
123
|
+
rl.question(' Enter your vote (approve/reject): ', (answer) => {
|
|
124
|
+
const normalized = answer.trim().toLowerCase();
|
|
125
|
+
if (normalized === 'approve' || normalized === 'reject') {
|
|
126
|
+
resolve(normalized);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.output.write(' Invalid input. Please enter "approve" or "reject".\n');
|
|
130
|
+
ask();
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
ask();
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Prompt the operator for their password to authenticate the approve vote.
|
|
139
|
+
*/
|
|
140
|
+
collectPassword(rl) {
|
|
141
|
+
return new Promise((resolve) => {
|
|
142
|
+
rl.question(' Enter your password to authenticate: ', (answer) => {
|
|
143
|
+
resolve(answer);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Record a failed authentication attempt for a proposal.
|
|
149
|
+
* If the maximum attempts are reached, trigger lockout.
|
|
150
|
+
*/
|
|
151
|
+
recordFailedAttempt(proposalId) {
|
|
152
|
+
let state = this.lockoutMap.get(proposalId);
|
|
153
|
+
if (!state) {
|
|
154
|
+
state = { failedAttempts: 0, lockedAt: null };
|
|
155
|
+
this.lockoutMap.set(proposalId, state);
|
|
156
|
+
}
|
|
157
|
+
state.failedAttempts += 1;
|
|
158
|
+
if (state.failedAttempts >= this.config.maxAttempts) {
|
|
159
|
+
state.lockedAt = Date.now();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Record a failed attempt externally (for use when authentication
|
|
164
|
+
* is validated outside this class, e.g., by the QuorumStateMachine).
|
|
165
|
+
*/
|
|
166
|
+
recordAuthFailure(proposalId) {
|
|
167
|
+
this.recordFailedAttempt(proposalId);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Reset failed attempts for a proposal (on successful authentication).
|
|
171
|
+
*/
|
|
172
|
+
resetAttempts(proposalId) {
|
|
173
|
+
this.lockoutMap.delete(proposalId);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
exports.CLIOperatorPrompt = CLIOperatorPrompt;
|
|
177
|
+
//# sourceMappingURL=cliOperatorPrompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliOperatorPrompt.js","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/services/cliOperatorPrompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview ContentAwareBlocksService — wraps BlocksService with identity
|
|
3
|
+
* validation and sealing via ContentIngestionService.
|
|
4
|
+
*
|
|
5
|
+
* Content is only accepted into the block store after:
|
|
6
|
+
* 1. Identity validation passes (signature, alias, membership proof, ban check)
|
|
7
|
+
* 2. Identity sealing completes (shard generation, distribution, identity replacement)
|
|
8
|
+
*
|
|
9
|
+
* @see Requirements 16
|
|
10
|
+
* @see Design: Content Ingestion Pipeline Integration (Task 19.2)
|
|
11
|
+
*/
|
|
12
|
+
import { BlockStoreOptions, BrightenResult, ContentIngestionResult, ContentWithIdentity, IBlockMetadata, IContentIngestionService, IdentityValidationError, QuorumError } from '@brightchain/brightchain-lib';
|
|
13
|
+
import { Member, PlatformID } from '@digitaldefiance/ecies-lib';
|
|
14
|
+
import { DefaultBackendIdType } from '../shared-types';
|
|
15
|
+
import { BlocksService } from './blocks';
|
|
16
|
+
/**
|
|
17
|
+
* Result of storing a block with identity validation and sealing.
|
|
18
|
+
*/
|
|
19
|
+
export interface ContentAwareStoreResult<TID extends PlatformID = Uint8Array> {
|
|
20
|
+
/** Block store result */
|
|
21
|
+
blockId: string;
|
|
22
|
+
metadata?: IBlockMetadata;
|
|
23
|
+
/** Identity ingestion result */
|
|
24
|
+
ingestion: ContentIngestionResult<TID>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* ContentAwareBlocksService wraps BlocksService with identity validation
|
|
28
|
+
* and sealing. Content is only stored after successful validation and
|
|
29
|
+
* shard distribution.
|
|
30
|
+
*
|
|
31
|
+
* @template TID - Platform ID type for frontend/backend DTO compatibility
|
|
32
|
+
*/
|
|
33
|
+
export declare class ContentAwareBlocksService<TID extends PlatformID = DefaultBackendIdType> {
|
|
34
|
+
private readonly blocksService;
|
|
35
|
+
private readonly contentIngestionService;
|
|
36
|
+
constructor(blocksService: BlocksService<TID>, contentIngestionService: IContentIngestionService<TID>);
|
|
37
|
+
/**
|
|
38
|
+
* Store a block with identity validation and sealing.
|
|
39
|
+
*
|
|
40
|
+
* Flow:
|
|
41
|
+
* 1. Validate and seal identity via ContentIngestionService
|
|
42
|
+
* 2. Store the block via BlocksService (only if step 1 succeeds)
|
|
43
|
+
* 3. Return combined result
|
|
44
|
+
*
|
|
45
|
+
* @param dataBuffer - The raw block data
|
|
46
|
+
* @param member - The authenticated member
|
|
47
|
+
* @param content - The content identity metadata for validation/sealing
|
|
48
|
+
* @param canRead - Whether the block can be read
|
|
49
|
+
* @param canPersist - Whether the block can be persisted
|
|
50
|
+
* @param options - Block store options
|
|
51
|
+
* @returns Combined block store and ingestion result
|
|
52
|
+
* @throws IdentityValidationError if identity validation fails
|
|
53
|
+
* @throws QuorumError if identity sealing fails
|
|
54
|
+
*/
|
|
55
|
+
storeBlockWithIdentity(dataBuffer: Buffer, member: Member, content: ContentWithIdentity<TID>, canRead?: boolean, canPersist?: boolean, options?: BlockStoreOptions): Promise<ContentAwareStoreResult<TID>>;
|
|
56
|
+
/**
|
|
57
|
+
* Store a block without identity validation (passthrough to BlocksService).
|
|
58
|
+
* Use this for system-internal blocks that don't carry user identity.
|
|
59
|
+
*/
|
|
60
|
+
storeBlock(dataBuffer: Buffer, member: Member, canRead?: boolean, canPersist?: boolean, options?: BlockStoreOptions): Promise<{
|
|
61
|
+
blockId: string;
|
|
62
|
+
metadata?: IBlockMetadata;
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Get a block by ID (passthrough to BlocksService).
|
|
66
|
+
*/
|
|
67
|
+
getBlock(blockId: string): Promise<{
|
|
68
|
+
data: Buffer;
|
|
69
|
+
metadata?: IBlockMetadata;
|
|
70
|
+
}>;
|
|
71
|
+
/**
|
|
72
|
+
* Get block metadata (passthrough to BlocksService).
|
|
73
|
+
*/
|
|
74
|
+
getBlockMetadata(blockId: string): Promise<IBlockMetadata | null>;
|
|
75
|
+
/**
|
|
76
|
+
* Delete a block (passthrough to BlocksService).
|
|
77
|
+
*/
|
|
78
|
+
deleteBlock(blockId: string): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Brighten a block (passthrough to BlocksService).
|
|
81
|
+
*/
|
|
82
|
+
brightenBlock(blockId: string, randomBlockCount: number): Promise<BrightenResult>;
|
|
83
|
+
/**
|
|
84
|
+
* Create a rejection from an IdentityValidationError.
|
|
85
|
+
*/
|
|
86
|
+
static createRejection(error: IdentityValidationError): import("@brightchain/brightchain-lib").ContentIngestionRejection;
|
|
87
|
+
/**
|
|
88
|
+
* Create a rejection from a QuorumError.
|
|
89
|
+
*/
|
|
90
|
+
static createSealingRejection(error: QuorumError): import("@brightchain/brightchain-lib").ContentIngestionRejection;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=contentAwareBlocksService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contentAwareBlocksService.d.ts","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/services/contentAwareBlocksService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,sBAAsB,EACtB,mBAAmB,EACnB,cAAc,EACd,wBAAwB,EACxB,uBAAuB,EACvB,WAAW,EACZ,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC;;GAEG;AACH,MAAM,WAAW,uBAAuB,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU;IAC1E,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,gCAAgC;IAChC,SAAS,EAAE,sBAAsB,CAAC,GAAG,CAAC,CAAC;CACxC;AAED;;;;;;GAMG;AACH,qBAAa,yBAAyB,CACpC,GAAG,SAAS,UAAU,GAAG,oBAAoB;IAG3C,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,uBAAuB;gBADvB,aAAa,EAAE,aAAa,CAAC,GAAG,CAAC,EACjC,uBAAuB,EAAE,wBAAwB,CAAC,GAAG,CAAC;IAGzE;;;;;;;;;;;;;;;;;OAiBG;IACG,sBAAsB,CAC1B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,mBAAmB,CAAC,GAAG,CAAC,EACjC,OAAO,UAAO,EACd,UAAU,UAAO,EACjB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAqBxC;;;OAGG;IACG,UAAU,CACd,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,UAAO,EACd,UAAU,UAAO,EACjB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAE,CAAC;IAU1D;;OAEG;IACG,QAAQ,CACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAE,CAAC;IAIvD;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAIvE;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjD;;OAEG;IACG,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,cAAc,CAAC;IAI1B;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,uBAAuB;IAIrD;;OAEG;IACH,MAAM,CAAC,sBAAsB,CAAC,KAAK,EAAE,WAAW;CAGjD"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview ContentAwareBlocksService — wraps BlocksService with identity
|
|
4
|
+
* validation and sealing via ContentIngestionService.
|
|
5
|
+
*
|
|
6
|
+
* Content is only accepted into the block store after:
|
|
7
|
+
* 1. Identity validation passes (signature, alias, membership proof, ban check)
|
|
8
|
+
* 2. Identity sealing completes (shard generation, distribution, identity replacement)
|
|
9
|
+
*
|
|
10
|
+
* @see Requirements 16
|
|
11
|
+
* @see Design: Content Ingestion Pipeline Integration (Task 19.2)
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.ContentAwareBlocksService = void 0;
|
|
15
|
+
const contentIngestionService_1 = require("./contentIngestionService");
|
|
16
|
+
/**
|
|
17
|
+
* ContentAwareBlocksService wraps BlocksService with identity validation
|
|
18
|
+
* and sealing. Content is only stored after successful validation and
|
|
19
|
+
* shard distribution.
|
|
20
|
+
*
|
|
21
|
+
* @template TID - Platform ID type for frontend/backend DTO compatibility
|
|
22
|
+
*/
|
|
23
|
+
class ContentAwareBlocksService {
|
|
24
|
+
constructor(blocksService, contentIngestionService) {
|
|
25
|
+
this.blocksService = blocksService;
|
|
26
|
+
this.contentIngestionService = contentIngestionService;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Store a block with identity validation and sealing.
|
|
30
|
+
*
|
|
31
|
+
* Flow:
|
|
32
|
+
* 1. Validate and seal identity via ContentIngestionService
|
|
33
|
+
* 2. Store the block via BlocksService (only if step 1 succeeds)
|
|
34
|
+
* 3. Return combined result
|
|
35
|
+
*
|
|
36
|
+
* @param dataBuffer - The raw block data
|
|
37
|
+
* @param member - The authenticated member
|
|
38
|
+
* @param content - The content identity metadata for validation/sealing
|
|
39
|
+
* @param canRead - Whether the block can be read
|
|
40
|
+
* @param canPersist - Whether the block can be persisted
|
|
41
|
+
* @param options - Block store options
|
|
42
|
+
* @returns Combined block store and ingestion result
|
|
43
|
+
* @throws IdentityValidationError if identity validation fails
|
|
44
|
+
* @throws QuorumError if identity sealing fails
|
|
45
|
+
*/
|
|
46
|
+
async storeBlockWithIdentity(dataBuffer, member, content, canRead = true, canPersist = true, options) {
|
|
47
|
+
// Step 1: Validate and seal identity — block store write is gated on this
|
|
48
|
+
const ingestionResult = await this.contentIngestionService.processContent(content);
|
|
49
|
+
// Step 2: Store the block only after successful validation and sealing
|
|
50
|
+
const storeResult = await this.blocksService.storeBlock(dataBuffer, member, canRead, canPersist, options);
|
|
51
|
+
return {
|
|
52
|
+
blockId: storeResult.blockId,
|
|
53
|
+
metadata: storeResult.metadata,
|
|
54
|
+
ingestion: ingestionResult,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Store a block without identity validation (passthrough to BlocksService).
|
|
59
|
+
* Use this for system-internal blocks that don't carry user identity.
|
|
60
|
+
*/
|
|
61
|
+
async storeBlock(dataBuffer, member, canRead = true, canPersist = true, options) {
|
|
62
|
+
return this.blocksService.storeBlock(dataBuffer, member, canRead, canPersist, options);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get a block by ID (passthrough to BlocksService).
|
|
66
|
+
*/
|
|
67
|
+
async getBlock(blockId) {
|
|
68
|
+
return this.blocksService.getBlock(blockId);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get block metadata (passthrough to BlocksService).
|
|
72
|
+
*/
|
|
73
|
+
async getBlockMetadata(blockId) {
|
|
74
|
+
return this.blocksService.getBlockMetadata(blockId);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Delete a block (passthrough to BlocksService).
|
|
78
|
+
*/
|
|
79
|
+
async deleteBlock(blockId) {
|
|
80
|
+
return this.blocksService.deleteBlock(blockId);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Brighten a block (passthrough to BlocksService).
|
|
84
|
+
*/
|
|
85
|
+
async brightenBlock(blockId, randomBlockCount) {
|
|
86
|
+
return this.blocksService.brightenBlock(blockId, randomBlockCount);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Create a rejection from an IdentityValidationError.
|
|
90
|
+
*/
|
|
91
|
+
static createRejection(error) {
|
|
92
|
+
return contentIngestionService_1.ContentIngestionService.createRejection(error);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Create a rejection from a QuorumError.
|
|
96
|
+
*/
|
|
97
|
+
static createSealingRejection(error) {
|
|
98
|
+
return contentIngestionService_1.ContentIngestionService.createSealingRejection(error);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.ContentAwareBlocksService = ContentAwareBlocksService;
|
|
102
|
+
//# sourceMappingURL=contentAwareBlocksService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contentAwareBlocksService.js","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/services/contentAwareBlocksService.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAeH,uEAAoE;AAapE;;;;;;GAMG;AACH,MAAa,yBAAyB;IAGpC,YACmB,aAAiC,EACjC,uBAAsD;QADtD,kBAAa,GAAb,aAAa,CAAoB;QACjC,4BAAuB,GAAvB,uBAAuB,CAA+B;IACtE,CAAC;IAEJ;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,sBAAsB,CAC1B,UAAkB,EAClB,MAAc,EACd,OAAiC,EACjC,OAAO,GAAG,IAAI,EACd,UAAU,GAAG,IAAI,EACjB,OAA2B;QAE3B,0EAA0E;QAC1E,MAAM,eAAe,GACnB,MAAM,IAAI,CAAC,uBAAuB,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAE7D,uEAAuE;QACvE,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,CACrD,UAAU,EACV,MAAM,EACN,OAAO,EACP,UAAU,EACV,OAAO,CACR,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,QAAQ,EAAE,WAAW,CAAC,QAAQ;YAC9B,SAAS,EAAE,eAAe;SAC3B,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CACd,UAAkB,EAClB,MAAc,EACd,OAAO,GAAG,IAAI,EACd,UAAU,GAAG,IAAI,EACjB,OAA2B;QAE3B,OAAO,IAAI,CAAC,aAAa,CAAC,UAAU,CAClC,UAAU,EACV,MAAM,EACN,OAAO,EACP,UAAU,EACV,OAAO,CACR,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CACZ,OAAe;QAEf,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAAC,OAAe;QACpC,OAAO,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,OAAe;QAC/B,OAAO,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CACjB,OAAe,EACf,gBAAwB;QAExB,OAAO,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,KAA8B;QACnD,OAAO,iDAAuB,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,sBAAsB,CAAC,KAAkB;QAC9C,OAAO,iDAAuB,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAC/D,CAAC;CACF;AAxHD,8DAwHC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview ContentIngestionService — wires identity validation and sealing
|
|
3
|
+
* into the content ingestion path.
|
|
4
|
+
*
|
|
5
|
+
* Before content is accepted into the block store, this service:
|
|
6
|
+
* 1. Validates the content identity via IdentityValidator
|
|
7
|
+
* 2. Seals the identity via IdentitySealingPipeline (generates shards, replaces identity)
|
|
8
|
+
* 3. Returns the processed content ready for block store acceptance
|
|
9
|
+
*
|
|
10
|
+
* @see Requirements 16
|
|
11
|
+
* @see Design: Content Ingestion Pipeline Integration (Task 19)
|
|
12
|
+
*/
|
|
13
|
+
import { ContentIngestionRejection, ContentIngestionResult, ContentWithIdentity, IContentIngestionService, IdentityValidationError, IIdentitySealingPipeline, IIdentityValidator, QuorumError } from '@brightchain/brightchain-lib';
|
|
14
|
+
import { PlatformID } from '@digitaldefiance/ecies-lib';
|
|
15
|
+
/**
|
|
16
|
+
* ContentIngestionService orchestrates identity validation and sealing
|
|
17
|
+
* before content is accepted into the block store.
|
|
18
|
+
*
|
|
19
|
+
* @template TID - Platform ID type for frontend/backend DTO compatibility
|
|
20
|
+
*/
|
|
21
|
+
export declare class ContentIngestionService<TID extends PlatformID = Uint8Array> implements IContentIngestionService<TID> {
|
|
22
|
+
private readonly identityValidator;
|
|
23
|
+
private readonly identitySealingPipeline;
|
|
24
|
+
constructor(identityValidator: IIdentityValidator<TID>, identitySealingPipeline: IIdentitySealingPipeline<TID>);
|
|
25
|
+
/**
|
|
26
|
+
* Process content through identity validation and sealing.
|
|
27
|
+
*
|
|
28
|
+
* Steps:
|
|
29
|
+
* 1. Validate identity (signature, alias status, membership proof, ban/suspend check)
|
|
30
|
+
* 2. Seal identity (generate shards, replace identity field, distribute encrypted shards)
|
|
31
|
+
* 3. Return processed content with recovery record ID
|
|
32
|
+
*
|
|
33
|
+
* @param content - The content with identity to validate and seal
|
|
34
|
+
* @returns Ingestion result with processed content
|
|
35
|
+
* @throws IdentityValidationError with specific error type on validation failure
|
|
36
|
+
* @throws QuorumError with IdentitySealingFailed on sealing failure
|
|
37
|
+
*/
|
|
38
|
+
processContent(content: ContentWithIdentity<TID>): Promise<ContentIngestionResult<TID>>;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the alias name from content's identity recovery record.
|
|
41
|
+
* The IdentityValidator already confirmed the alias exists and is active,
|
|
42
|
+
* so the sealing pipeline handles alias lookup internally.
|
|
43
|
+
*/
|
|
44
|
+
private resolveAliasName;
|
|
45
|
+
/**
|
|
46
|
+
* Create a rejection result from an IdentityValidationError.
|
|
47
|
+
*
|
|
48
|
+
* @param error - The validation error
|
|
49
|
+
* @returns A structured rejection result
|
|
50
|
+
*/
|
|
51
|
+
static createRejection(error: IdentityValidationError): ContentIngestionRejection;
|
|
52
|
+
/**
|
|
53
|
+
* Create a rejection result from a QuorumError (sealing failure).
|
|
54
|
+
*
|
|
55
|
+
* @param error - The quorum error
|
|
56
|
+
* @returns A structured rejection result
|
|
57
|
+
*/
|
|
58
|
+
static createSealingRejection(error: QuorumError): ContentIngestionRejection;
|
|
59
|
+
/**
|
|
60
|
+
* Determine if an error is an IdentityValidationError.
|
|
61
|
+
*/
|
|
62
|
+
static isValidationError(error: unknown): error is IdentityValidationError;
|
|
63
|
+
/**
|
|
64
|
+
* Determine if an error is a QuorumError.
|
|
65
|
+
*/
|
|
66
|
+
static isQuorumError(error: unknown): error is QuorumError;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=contentIngestionService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contentIngestionService.d.ts","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/services/contentIngestionService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,wBAAwB,EAExB,uBAAuB,EAEvB,wBAAwB,EACxB,kBAAkB,EAClB,WAAW,EAEZ,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAwBxD;;;;;GAKG;AACH,qBAAa,uBAAuB,CAClC,GAAG,SAAS,UAAU,GAAG,UAAU,CACnC,YAAW,wBAAwB,CAAC,GAAG,CAAC;IAEtC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,uBAAuB;gBADvB,iBAAiB,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAC1C,uBAAuB,EAAE,wBAAwB,CAAC,GAAG,CAAC;IAGzE;;;;;;;;;;;;OAYG;IACG,cAAc,CAClB,OAAO,EAAE,mBAAmB,CAAC,GAAG,CAAC,GAChC,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC;IA2BvC;;;;OAIG;YACW,gBAAgB;IAS9B;;;;;OAKG;IACH,MAAM,CAAC,eAAe,CACpB,KAAK,EAAE,uBAAuB,GAC7B,yBAAyB;IAW5B;;;;;OAKG;IACH,MAAM,CAAC,sBAAsB,CAAC,KAAK,EAAE,WAAW,GAAG,yBAAyB;IAwB5E;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,uBAAuB;IAI1E;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW;CAG3D"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview ContentIngestionService — wires identity validation and sealing
|
|
4
|
+
* into the content ingestion path.
|
|
5
|
+
*
|
|
6
|
+
* Before content is accepted into the block store, this service:
|
|
7
|
+
* 1. Validates the content identity via IdentityValidator
|
|
8
|
+
* 2. Seals the identity via IdentitySealingPipeline (generates shards, replaces identity)
|
|
9
|
+
* 3. Returns the processed content ready for block store acceptance
|
|
10
|
+
*
|
|
11
|
+
* @see Requirements 16
|
|
12
|
+
* @see Design: Content Ingestion Pipeline Integration (Task 19)
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ContentIngestionService = void 0;
|
|
16
|
+
const brightchain_lib_1 = require("@brightchain/brightchain-lib");
|
|
17
|
+
/**
|
|
18
|
+
* Human-readable error messages for each IdentityValidationErrorType.
|
|
19
|
+
*/
|
|
20
|
+
const VALIDATION_ERROR_MESSAGES = {
|
|
21
|
+
[brightchain_lib_1.IdentityValidationErrorType.InvalidSignature]: 'Content signature does not match the claimed identity public key',
|
|
22
|
+
[brightchain_lib_1.IdentityValidationErrorType.UnregisteredAlias]: 'The alias used for content publication is not registered',
|
|
23
|
+
[brightchain_lib_1.IdentityValidationErrorType.InactiveAlias]: 'The alias used for content publication has been deactivated',
|
|
24
|
+
[brightchain_lib_1.IdentityValidationErrorType.InvalidMembershipProof]: 'The membership proof for anonymous content is invalid',
|
|
25
|
+
[brightchain_lib_1.IdentityValidationErrorType.MissingMembershipProof]: 'Anonymous content must include a valid membership proof',
|
|
26
|
+
[brightchain_lib_1.IdentityValidationErrorType.BannedUser]: 'The content creator has been banned from the network',
|
|
27
|
+
[brightchain_lib_1.IdentityValidationErrorType.SuspendedUser]: 'The content creator is currently suspended',
|
|
28
|
+
[brightchain_lib_1.IdentityValidationErrorType.ShardVerificationFailed]: 'Identity shard verification failed during sealing',
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* ContentIngestionService orchestrates identity validation and sealing
|
|
32
|
+
* before content is accepted into the block store.
|
|
33
|
+
*
|
|
34
|
+
* @template TID - Platform ID type for frontend/backend DTO compatibility
|
|
35
|
+
*/
|
|
36
|
+
class ContentIngestionService {
|
|
37
|
+
constructor(identityValidator, identitySealingPipeline) {
|
|
38
|
+
this.identityValidator = identityValidator;
|
|
39
|
+
this.identitySealingPipeline = identitySealingPipeline;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Process content through identity validation and sealing.
|
|
43
|
+
*
|
|
44
|
+
* Steps:
|
|
45
|
+
* 1. Validate identity (signature, alias status, membership proof, ban/suspend check)
|
|
46
|
+
* 2. Seal identity (generate shards, replace identity field, distribute encrypted shards)
|
|
47
|
+
* 3. Return processed content with recovery record ID
|
|
48
|
+
*
|
|
49
|
+
* @param content - The content with identity to validate and seal
|
|
50
|
+
* @returns Ingestion result with processed content
|
|
51
|
+
* @throws IdentityValidationError with specific error type on validation failure
|
|
52
|
+
* @throws QuorumError with IdentitySealingFailed on sealing failure
|
|
53
|
+
*/
|
|
54
|
+
async processContent(content) {
|
|
55
|
+
// Step 1: Validate identity
|
|
56
|
+
const validationResult = await this.identityValidator.validateContent(content);
|
|
57
|
+
// Step 2: Determine alias name for alias mode
|
|
58
|
+
let aliasName;
|
|
59
|
+
if (validationResult.identityMode === brightchain_lib_1.IdentityMode.Alias) {
|
|
60
|
+
aliasName = await this.resolveAliasName(content);
|
|
61
|
+
}
|
|
62
|
+
// Step 3: Seal identity through the pipeline
|
|
63
|
+
const sealingResult = await this.identitySealingPipeline.sealIdentity(content, validationResult.identityMode, aliasName);
|
|
64
|
+
return {
|
|
65
|
+
accepted: true,
|
|
66
|
+
processedContent: sealingResult.modifiedContent,
|
|
67
|
+
recoveryRecordId: sealingResult.recoveryRecordId,
|
|
68
|
+
identityMode: validationResult.identityMode,
|
|
69
|
+
resolvedMemberId: validationResult.resolvedMemberId,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Resolve the alias name from content's identity recovery record.
|
|
74
|
+
* The IdentityValidator already confirmed the alias exists and is active,
|
|
75
|
+
* so the sealing pipeline handles alias lookup internally.
|
|
76
|
+
*/
|
|
77
|
+
async resolveAliasName(_content) {
|
|
78
|
+
// The alias name is determined by the IdentitySealingPipeline
|
|
79
|
+
// based on the content's identityRecoveryRecordId.
|
|
80
|
+
// The sealing pipeline handles alias lookup internally.
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create a rejection result from an IdentityValidationError.
|
|
85
|
+
*
|
|
86
|
+
* @param error - The validation error
|
|
87
|
+
* @returns A structured rejection result
|
|
88
|
+
*/
|
|
89
|
+
static createRejection(error) {
|
|
90
|
+
const errorType = error.type;
|
|
91
|
+
return {
|
|
92
|
+
accepted: false,
|
|
93
|
+
reason: VALIDATION_ERROR_MESSAGES[errorType] ??
|
|
94
|
+
`Identity validation failed: ${errorType}`,
|
|
95
|
+
errorType,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Create a rejection result from a QuorumError (sealing failure).
|
|
100
|
+
*
|
|
101
|
+
* @param error - The quorum error
|
|
102
|
+
* @returns A structured rejection result
|
|
103
|
+
*/
|
|
104
|
+
static createSealingRejection(error) {
|
|
105
|
+
const errorType = error.type;
|
|
106
|
+
let reason;
|
|
107
|
+
switch (errorType) {
|
|
108
|
+
case brightchain_lib_1.QuorumErrorType.IdentitySealingFailed:
|
|
109
|
+
reason =
|
|
110
|
+
'Identity sealing failed during shard generation or distribution';
|
|
111
|
+
break;
|
|
112
|
+
case brightchain_lib_1.QuorumErrorType.ShardVerificationFailed:
|
|
113
|
+
reason =
|
|
114
|
+
'Identity shard verification failed — shards do not reconstruct correctly';
|
|
115
|
+
break;
|
|
116
|
+
default:
|
|
117
|
+
reason = `Identity sealing failed: ${errorType}`;
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
accepted: false,
|
|
121
|
+
reason,
|
|
122
|
+
errorType: 'IDENTITY_SEALING_FAILED',
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Determine if an error is an IdentityValidationError.
|
|
127
|
+
*/
|
|
128
|
+
static isValidationError(error) {
|
|
129
|
+
return error instanceof brightchain_lib_1.IdentityValidationError;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Determine if an error is a QuorumError.
|
|
133
|
+
*/
|
|
134
|
+
static isQuorumError(error) {
|
|
135
|
+
return error instanceof brightchain_lib_1.QuorumError;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.ContentIngestionService = ContentIngestionService;
|
|
139
|
+
//# sourceMappingURL=contentIngestionService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contentIngestionService.js","sourceRoot":"","sources":["../../../../../brightchain-api-lib/src/lib/services/contentIngestionService.ts"],"names":[],"mappings":"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"}
|