@ibgib/node-gib 0.0.20 → 0.0.21

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.
Files changed (44) hide show
  1. package/dist/email/verify/email-verify-helpers.d.mts +6 -1
  2. package/dist/email/verify/email-verify-helpers.d.mts.map +1 -1
  3. package/dist/email/verify/email-verify-helpers.mjs +6 -2
  4. package/dist/email/verify/email-verify-helpers.mjs.map +1 -1
  5. package/dist/identity/sso/sso-custodian-service.d.mts +8 -0
  6. package/dist/identity/sso/sso-custodian-service.d.mts.map +1 -1
  7. package/dist/identity/sso/sso-custodian-service.mjs +126 -77
  8. package/dist/identity/sso/sso-custodian-service.mjs.map +1 -1
  9. package/dist/serve-gib/handlers/api/email/email-verification-code.handler.d.mts.map +1 -1
  10. package/dist/serve-gib/handlers/api/email/email-verification-code.handler.mjs +50 -4
  11. package/dist/serve-gib/handlers/api/email/email-verification-code.handler.mjs.map +1 -1
  12. package/dist/serve-gib/handlers/api/identity/keystone-custodian-add-master-password.handler.d.mts +8 -5
  13. package/dist/serve-gib/handlers/api/identity/keystone-custodian-add-master-password.handler.d.mts.map +1 -1
  14. package/dist/serve-gib/handlers/api/identity/keystone-custodian-add-master-password.handler.mjs +15 -11
  15. package/dist/serve-gib/handlers/api/identity/keystone-custodian-add-master-password.handler.mjs.map +1 -1
  16. package/dist/serve-gib/handlers/api/identity/keystone-custodian-register-delegate.handler.d.mts.map +1 -1
  17. package/dist/serve-gib/handlers/api/identity/keystone-custodian-register-delegate.handler.mjs +5 -1
  18. package/dist/serve-gib/handlers/api/identity/keystone-custodian-register-delegate.handler.mjs.map +1 -1
  19. package/dist/serve-gib/handlers/api/keystone/keystone-evolve.handler.d.mts.map +1 -1
  20. package/dist/serve-gib/handlers/api/keystone/keystone-evolve.handler.mjs +6 -1
  21. package/dist/serve-gib/handlers/api/keystone/keystone-evolve.handler.mjs.map +1 -1
  22. package/dist/serve-gib/handlers/api/keystone/sso-config.handler.d.mts.map +1 -1
  23. package/dist/serve-gib/handlers/api/keystone/sso-config.handler.mjs +2 -11
  24. package/dist/serve-gib/handlers/api/keystone/sso-config.handler.mjs.map +1 -1
  25. package/dist/serve-gib/handlers/api/keystone/sso-link.handler.d.mts.map +1 -1
  26. package/dist/serve-gib/handlers/api/keystone/sso-link.handler.mjs +66 -26
  27. package/dist/serve-gib/handlers/api/keystone/sso-link.handler.mjs.map +1 -1
  28. package/dist/serve-gib/handlers/api/keystone/sso-login.handler.d.mts.map +1 -1
  29. package/dist/serve-gib/handlers/api/keystone/sso-login.handler.mjs +2 -10
  30. package/dist/serve-gib/handlers/api/keystone/sso-login.handler.mjs.map +1 -1
  31. package/dist/serve-gib/identity-index/identity-index-service.d.mts.map +1 -1
  32. package/dist/serve-gib/identity-index/identity-index-service.mjs +34 -19
  33. package/dist/serve-gib/identity-index/identity-index-service.mjs.map +1 -1
  34. package/package.json +2 -2
  35. package/src/email/verify/email-verify-helpers.mts +13 -2
  36. package/src/identity/sso/sso-custodian-service.mts +129 -84
  37. package/src/serve-gib/handlers/api/email/email-verification-code.handler.mts +52 -5
  38. package/src/serve-gib/handlers/api/identity/keystone-custodian-add-master-password.handler.mts +24 -17
  39. package/src/serve-gib/handlers/api/identity/keystone-custodian-register-delegate.handler.mts +6 -1
  40. package/src/serve-gib/handlers/api/keystone/keystone-evolve.handler.mts +6 -1
  41. package/src/serve-gib/handlers/api/keystone/sso-config.handler.mts +2 -12
  42. package/src/serve-gib/handlers/api/keystone/sso-link.handler.mts +61 -26
  43. package/src/serve-gib/handlers/api/keystone/sso-login.handler.mts +2 -11
  44. package/src/serve-gib/identity-index/identity-index-service.mts +28 -18
@@ -1 +1 @@
1
- {"version":3,"file":"identity-index-service.mjs","sourceRoot":"","sources":["../../../src/serve-gib/identity-index/identity-index-service.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"identity-index-service.mjs","sourceRoot":"","sources":["../../../src/serve-gib/identity-index/identity-index-service.mts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibgib/node-gib",
3
- "version": "0.0.20",
3
+ "version": "0.0.21",
4
4
  "description": "Node and server-specific ibGib code, i.e., things that don't run in the browser.",
5
5
  "funding": {
6
6
  "type": "individual",
@@ -26,7 +26,7 @@
26
26
  "dependencies": {
27
27
  "@ibgib/helper-gib": "^0.0.37",
28
28
  "@ibgib/ts-gib": "^0.5.34",
29
- "@ibgib/core-gib": "^0.1.75",
29
+ "@ibgib/core-gib": "^0.1.76",
30
30
  "@ibgib/encrypt-gib": "^0.3.1"
31
31
  },
32
32
  "devDependencies": {
@@ -236,13 +236,18 @@ export interface SavePendingCodeRecordOptions {
236
236
  code: string;
237
237
  maxAttempts?: number;
238
238
  ttlMs?: number;
239
+ resendCount?: number;
240
+ attempts?: number;
239
241
  }
240
242
 
241
243
  export interface PendingCodeRecord {
242
244
  codeHash: string;
245
+ rawCode?: string;
243
246
  attempts: number;
244
247
  maxAttempts: number;
245
248
  expiresAt: number;
249
+ dispatchedAt: number;
250
+ resendCount: number;
246
251
  }
247
252
 
248
253
  /**
@@ -253,16 +258,22 @@ export async function savePendingCodeRecord({
253
258
  code,
254
259
  maxAttempts = 5,
255
260
  ttlMs = DEFAULT_MAGIC_LINK_TTL_MS,
256
- }: SavePendingCodeRecordOptions): Promise<void> {
261
+ resendCount = 0,
262
+ attempts = 0,
263
+ }: SavePendingCodeRecordOptions): Promise<PendingCodeRecord> {
257
264
  const codeHash = await hash({ s: `verificationcode${code}` });
258
265
  const record: PendingCodeRecord = {
259
266
  codeHash,
260
- attempts: 0,
267
+ rawCode: code,
268
+ attempts,
261
269
  maxAttempts,
262
270
  expiresAt: Date.now() + ttlMs,
271
+ dispatchedAt: Date.now(),
272
+ resendCount,
263
273
  };
264
274
  const codeFilePath = path.join(pendingDir, 'code.json');
265
275
  await fs.writeFile(codeFilePath, JSON.stringify(record, null, 2), 'utf-8');
276
+ return record;
266
277
  }
267
278
 
268
279
  /**
@@ -10,11 +10,15 @@ import { KeystoneStrategyFactory } from '@ibgib/core-gib/dist/keystone/strategy/
10
10
  import { MetaspaceService } from '@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs';
11
11
  import { IbGibSpaceAny } from '@ibgib/core-gib/dist/witness/space/space-base-v1.mjs';
12
12
 
13
+ import { GLOBAL_LOG_A_LOT } from '../../constants.mjs';
14
+ import { loadSsoServerConfig } from './sso-config-helper.mjs';
13
15
  import {
14
16
  SsoServerConfig, SsoProviderId, OAuthUserInfo, SsoProviderServerConfig,
15
17
  SsoProviderClientConfig
16
18
  } from './sso-types.mjs';
17
19
 
20
+ const logalot = GLOBAL_LOG_A_LOT || true;
21
+
18
22
  interface JwkKey {
19
23
  kty: string;
20
24
  alg?: string;
@@ -62,33 +66,42 @@ export class SsoCustodianService {
62
66
  * - Generator: Client/Server (Derived from environmental configuration and sent by client).
63
67
  */
64
68
  async getOAuthUserInfo(providerId: SsoProviderId, code: string, redirectUri: string): Promise<OAuthUserInfo> {
65
- const lc = `${this.lc}[${this.getOAuthUserInfo.name}]`;
66
- const providerConfig = this.config.providers[providerId];
67
- if (!providerConfig) {
68
- throw new Error(`Provider '${providerId}' is not configured on this server. (E: c28900abfefd23e89cf23f12)`);
69
- }
69
+ const lc = `[${this.getOAuthUserInfo.name}]`;
70
+ try {
71
+ if (logalot) { console.log(`${lc} starting... (I: 3ad578b5065ec6d5517469571a4da826)`); }
70
72
 
71
- console.log(`${lc} Exchanging code for provider: ${providerId}`);
73
+ const providerConfig = this.config.providers[providerId];
74
+ if (!providerConfig) {
75
+ throw new Error(`Provider '${providerId}' is not configured on this server. (E: c28900abfefd23e89cf23f12)`);
76
+ }
72
77
 
73
- // 1. Exchange authorization code for tokens
74
- const tokens = await this.exchangeCodeForTokens(providerConfig, code, redirectUri);
78
+ console.log(`${lc} Exchanging code for provider: ${providerId}`);
75
79
 
76
- // 2. Retrieve and normalize user info
77
- if (providerId === 'google') {
78
- // Google returns an id_token (JWT) directly containing user info
79
- if (!tokens.id_token) {
80
- throw new Error(`Google token exchange did not return id_token. (E: e28900abfefd23e89cf45f23)`);
81
- }
82
- return this.verifyAndNormalizeGoogleToken(tokens.id_token);
83
- } else if (providerId === 'github') {
84
- // GitHub requires calling the /user API using the access_token
85
- if (!tokens.access_token) {
86
- throw new Error(`GitHub token exchange did not return access_token. (E: a28900abfefd23e89cf56f34)`);
80
+ // 1. Exchange authorization code for tokens
81
+ const tokens = await this.exchangeCodeForTokens(providerConfig, code, redirectUri);
82
+
83
+ // 2. Retrieve and normalize user info
84
+ if (providerId === 'google') {
85
+ // Google returns an id_token (JWT) directly containing user info
86
+ if (!tokens.id_token) {
87
+ throw new Error(`Google token exchange did not return id_token. (E: e28900abfefd23e89cf45f23)`);
88
+ }
89
+ return this.verifyAndNormalizeGoogleToken(tokens.id_token);
90
+ } else if (providerId === 'github') {
91
+ // GitHub requires calling the /user API using the access_token
92
+ if (!tokens.access_token) {
93
+ throw new Error(`GitHub token exchange did not return access_token. (E: a28900abfefd23e89cf56f34)`);
94
+ }
95
+ return this.fetchAndNormalizeGithubUser(providerConfig, tokens.access_token);
87
96
  }
88
- return this.fetchAndNormalizeGithubUser(providerConfig, tokens.access_token);
89
- }
90
97
 
91
- throw new Error(`Unsupported provider: ${providerId}. (E: d28900abfefd23e89cf67f45)`);
98
+ throw new Error(`Unsupported provider: ${providerId}. (E: d28900abfefd23e89cf67f45)`);
99
+ } catch (error) {
100
+ console.error(`${lc} ${extractErrorMsg(error)}`);
101
+ throw error;
102
+ } finally {
103
+ if (logalot) { console.log(`${lc} complete.`); }
104
+ }
92
105
  }
93
106
 
94
107
  /**
@@ -413,76 +426,87 @@ export class SsoCustodianService {
413
426
  metaspace: MetaspaceService;
414
427
  space: IbGibSpaceAny;
415
428
  }): Promise<KeystoneChallengePool> {
416
- // 1. Fetch target keystone
417
- const keystoneService = new KeystoneService_V1();
418
- const targetKeystone = await keystoneService.getLatestKeystone({
419
- addr: keystoneAddr,
420
- metaspace,
421
- space
422
- });
429
+ const lc = `[${this.createCustodianChallengePool.name}]`;
430
+ try {
431
+ if (logalot) { console.log(`${lc} starting... (I: 4238580990ff19dd2815d5186ffa0826)`); }
432
+
433
+ // 1. Fetch target keystone
434
+ const keystoneService = new KeystoneService_V1();
435
+ const targetKeystone = await keystoneService.getLatestKeystone({
436
+ addr: keystoneAddr,
437
+ metaspace,
438
+ space
439
+ });
423
440
 
424
- if (!targetKeystone) {
425
- throw new Error(`Keystone not found for address: ${keystoneAddr} (E: 8a9c2b1d3e5f6a7b8c9d0e1f2a3b4c5d)`);
426
- }
441
+ if (!targetKeystone) {
442
+ throw new Error(`Keystone not found for address: ${keystoneAddr} (E: 8a9c2b1d3e5f6a7b8c9d0e1f2a3b4c5d)`);
443
+ }
427
444
 
428
- // 2. Locate native manage pool
429
- const userManagePool = targetKeystone.data?.challengePools.find(p => p.id === POOL_ID_MANAGE);
430
- if (!userManagePool) {
431
- throw new Error(`Keystone manage pool not found. Custodian manage pool must match the user manage pool's security config. (E: 7c4e5f6a7b8c9d0e1f2a3b4c5e6f7a8b)`);
432
- }
445
+ // 2. Locate native manage pool
446
+ const userManagePool = targetKeystone.data?.challengePools.find(p => p.id === POOL_ID_MANAGE);
447
+ if (!userManagePool) {
448
+ throw new Error(`Keystone manage pool not found. Custodian manage pool must match the user manage pool's security config. (E: 7c4e5f6a7b8c9d0e1f2a3b4c5e6f7a8b)`);
449
+ }
433
450
 
434
- // 3. Dynamic poolId based on providerId with regex validation
435
- if (!providerId || !KEYSTONE_POOL_ID_REGEXP.test(providerId)) {
436
- throw new Error(`Invalid providerId: "${providerId}". Must match ${KEYSTONE_POOL_ID_REGEXP} (E: 3a2c4e5f6a7b8c9d0e1f2a3b4c5e6f)`);
437
- }
438
- const poolId = `custodian-manage-${providerId}`;
451
+ // 3. Dynamic poolId based on providerId with regex validation
452
+ if (!providerId || !KEYSTONE_POOL_ID_REGEXP.test(providerId)) {
453
+ throw new Error(`Invalid providerId: "${providerId}". Must match ${KEYSTONE_POOL_ID_REGEXP} (E: 3a2c4e5f6a7b8c9d0e1f2a3b4c5e6f)`);
454
+ }
455
+ const poolId = `custodian-manage-${providerId}`;
439
456
 
440
- // 4. Derive delegate secrets
441
- const custodianSecret = await this.deriveServerDelegateSecret(providerKey, userNonce);
457
+ // 4. Derive delegate secrets
458
+ const custodianSecret = await this.deriveServerDelegateSecret(providerKey, userNonce);
442
459
 
443
- const poolSalt = await hash({
444
- s: `${providerKey}:${userNonce}:salt`,
445
- algorithm: HashAlgorithm.sha_256
446
- });
447
- const poolSaltShort = poolSalt.substring(0, 16);
448
-
449
- // 5. Clone user's manage pool config, updating only ID, salt, and allowedVerbs
450
- const config: KeystonePoolConfig = {
451
- ...userManagePool.config,
452
- id: poolId,
453
- salt: poolSaltShort,
454
- allowedVerbs: [KEYSTONE_VERB_MANAGE, KEYSTONE_VERB_REVOKE]
455
- };
460
+ const poolSalt = await hash({
461
+ s: `${providerKey}:${userNonce}:salt`,
462
+ algorithm: HashAlgorithm.sha_256
463
+ });
464
+ const poolSaltShort = poolSalt.substring(0, 16);
465
+
466
+ // 5. Clone user's manage pool config, updating only ID, salt, and allowedVerbs
467
+ const config: KeystonePoolConfig = {
468
+ ...userManagePool.config,
469
+ id: poolId,
470
+ salt: poolSaltShort,
471
+ allowedVerbs: [KEYSTONE_VERB_MANAGE, KEYSTONE_VERB_REVOKE]
472
+ };
473
+
474
+ const strategy = KeystoneStrategyFactory.create({ config });
475
+ const poolSecret = await strategy.derivePoolSecret({ masterSecret: custodianSecret });
476
+ const challenges: { [id: string]: any } = {};
477
+ const timestamp = Date.now().toString();
478
+
479
+ for (let i = 0; i < config.behavior.size; i++) {
480
+ const challengeId = await generateOpaqueChallengeId({
481
+ salt: config.salt,
482
+ timestamp,
483
+ index: i
484
+ });
485
+ const solution = await strategy.generateSolution({
486
+ poolSecret,
487
+ poolId: config.id,
488
+ challengeId
489
+ });
490
+ challenges[challengeId] = await strategy.generateChallenge({ solution });
491
+ }
456
492
 
457
- const strategy = KeystoneStrategyFactory.create({ config });
458
- const poolSecret = await strategy.derivePoolSecret({ masterSecret: custodianSecret });
459
- const challenges: { [id: string]: any } = {};
460
- const timestamp = Date.now().toString();
493
+ return {
494
+ id: poolId,
495
+ config,
496
+ challenges,
497
+ isForeign: true,
498
+ metadata: {
499
+ owner: 'custodian',
500
+ providerKey
501
+ }
502
+ };
461
503
 
462
- for (let i = 0; i < config.behavior.size; i++) {
463
- const challengeId = await generateOpaqueChallengeId({
464
- salt: config.salt,
465
- timestamp,
466
- index: i
467
- });
468
- const solution = await strategy.generateSolution({
469
- poolSecret,
470
- poolId: config.id,
471
- challengeId
472
- });
473
- challenges[challengeId] = await strategy.generateChallenge({ solution });
504
+ } catch (error) {
505
+ console.error(`${lc} ${extractErrorMsg(error)}`);
506
+ throw error;
507
+ } finally {
508
+ if (logalot) { console.log(`${lc} complete.`); }
474
509
  }
475
-
476
- return {
477
- id: poolId,
478
- config,
479
- challenges,
480
- isForeign: true,
481
- metadata: {
482
- owner: 'custodian',
483
- providerKey
484
- }
485
- };
486
510
  }
487
511
 
488
512
  /**
@@ -564,3 +588,24 @@ export class SsoCustodianService {
564
588
  }
565
589
  }
566
590
  }
591
+
592
+ let ssoCustodianService: SsoCustodianService | undefined;
593
+
594
+ /**
595
+ * Gets or initializes the singleton SsoCustodianService instance.
596
+ */
597
+ export function getSsoCustodianService(): SsoCustodianService {
598
+ if (!ssoCustodianService) {
599
+ const config = loadSsoServerConfig();
600
+ ssoCustodianService = new SsoCustodianService(config);
601
+ }
602
+ return ssoCustodianService;
603
+ }
604
+
605
+ /**
606
+ * Resets the singleton SsoCustodianService instance (useful for test resets).
607
+ */
608
+ export function resetSsoCustodianService(): void {
609
+ ssoCustodianService = undefined;
610
+ }
611
+
@@ -4,7 +4,10 @@
4
4
  * Handler for POST /api/email/verification-code
5
5
  */
6
6
 
7
- import { extractErrorMsg, getUUID } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
7
+ import * as path from 'node:path';
8
+ import * as fs from 'node:fs/promises';
9
+ import { existsSync } from 'node:fs';
10
+ import { extractErrorMsg, getUUID, delay } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
8
11
  import { EmailSenderAws } from '../../../../email/aws/email-sender-aws.mjs';
9
12
  // import { generateVerificationCode, getPendingTjpHash, savePendingCodeRecord, getPendingStagingDir, validateEmail } from '../../../../email/index.mjs';
10
13
  import { EmailSender, OutboundEmail } from '../../../../email/email-types.mjs';
@@ -13,7 +16,7 @@ import { API_PATH_REGEXES } from '../../../path-constants.mjs';
13
16
  import { RequestContext, ResponseResult, ServeGibHttpMethod } from '../../../types.mjs';
14
17
  import { ServeGibHandlerBase } from '../../handler-base.mjs';
15
18
  import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
16
- import { createDefaultEmailSender, generateVerificationCode, getPendingStagingDir, getPendingTjpHash, savePendingCodeRecord, savePendingStagingKeystone } from '../../../../email/verify/email-verify-helpers.mjs';
19
+ import { createDefaultEmailSender, generateVerificationCode, getPendingStagingDir, getPendingTjpHash, savePendingCodeRecord, savePendingStagingKeystone, PendingCodeRecord } from '../../../../email/verify/email-verify-helpers.mjs';
17
20
  import { validateEmail } from '../../../../email/email-helpers.mjs';
18
21
  import { normalizeEmail } from '../../../identity-index/identity-index-helpers.mjs';
19
22
 
@@ -75,11 +78,14 @@ export class EmailVerificationCodeHandler extends ServeGibHandlerBase {
75
78
  return this.error(400, 'Invalid email address format (E: e3f4a5b67890123456789abcdef012)');
76
79
  }
77
80
 
81
+ // Artificial delay to mitigate brute force & timing attacks (min 1s)
82
+ await delay(1000 + Math.random() * 500);
83
+
78
84
  const normEmail = normalizeEmail(email);
79
85
  const effectivePrimaryTjpAddr = primaryTjpAddr || `pending:${normEmail}`;
80
86
  const tjpHash = await getPendingTjpHash(effectivePrimaryTjpAddr);
81
87
 
82
- const code = generateVerificationCode();
88
+ let code: string = generateVerificationCode();
83
89
  if (reqCtx.dataDir && tjpHash) {
84
90
  let info = await getPendingStagingDir({ dataDir: reqCtx.dataDir, tjpHash });
85
91
  if (!info) {
@@ -93,8 +99,49 @@ export class EmailVerificationCodeHandler extends ServeGibHandlerBase {
93
99
  }
94
100
 
95
101
  if (info) {
96
- await savePendingCodeRecord({ pendingDir: info.pendingDir, code });
97
- if (logalot) { console.timeLog(timestampUUID, 'code record saved to pending staging'); }
102
+ const codeFilePath = path.join(info.pendingDir, 'code.json');
103
+ let existingRecord: PendingCodeRecord | undefined;
104
+ if (existsSync(codeFilePath)) {
105
+ try {
106
+ existingRecord = JSON.parse(await fs.readFile(codeFilePath, 'utf-8'));
107
+ } catch { /* ignore corrupted record */ }
108
+ }
109
+
110
+ const now = Date.now();
111
+ if (existingRecord) {
112
+ // Check 30-second cooldown
113
+ const elapsedMs = now - (existingRecord.dispatchedAt || 0);
114
+ if (elapsedMs < 30_000) {
115
+ const remainingSecs = Math.ceil((30_000 - elapsedMs) / 1000);
116
+ return this.error(429, `Please wait ${remainingSecs}s before requesting another verification code.`);
117
+ }
118
+
119
+ // Check Max Resend limit (5 resends per 15-minute window)
120
+ if (existingRecord.resendCount >= 5 && now < existingRecord.expiresAt) {
121
+ return this.error(429, 'Too many verification code requests. Please wait 15 minutes before trying again.');
122
+ }
123
+
124
+ // Reuse existing valid code if not expired and attempts < maxAttempts
125
+ if (existingRecord.rawCode && now < existingRecord.expiresAt && existingRecord.attempts < existingRecord.maxAttempts) {
126
+ code = existingRecord.rawCode;
127
+ existingRecord.dispatchedAt = now;
128
+ existingRecord.resendCount = (existingRecord.resendCount || 0) + 1;
129
+ await fs.writeFile(codeFilePath, JSON.stringify(existingRecord, null, 2), 'utf-8');
130
+ } else {
131
+ // Generate fresh code and increment resendCount
132
+ code = generateVerificationCode();
133
+ await savePendingCodeRecord({
134
+ pendingDir: info.pendingDir,
135
+ code,
136
+ resendCount: (existingRecord.resendCount || 0) + 1,
137
+ attempts: 0,
138
+ });
139
+ }
140
+ } else {
141
+ code = generateVerificationCode();
142
+ await savePendingCodeRecord({ pendingDir: info.pendingDir, code, resendCount: 0, attempts: 0 });
143
+ }
144
+ if (logalot) { console.timeLog(timestampUUID, 'code record processed in pending staging'); }
98
145
  } else {
99
146
  console.warn(`${lc} Failed to create or access pending staging directory for tjpHash ${tjpHash}`);
100
147
  }
@@ -13,6 +13,8 @@
13
13
  import { extractErrorMsg, hash } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
14
14
  import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
15
15
  import { getTjpAddr } from '@ibgib/core-gib/dist/common/other/ibgib-helper.mjs';
16
+ import { getDependencyGraph } from '@ibgib/core-gib/dist/common/other/graph-helper.mjs';
17
+ import { FlatIbGibGraph } from '@ibgib/core-gib/dist/common/other/graph-types.mjs';
16
18
  import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
17
19
  import { KeystoneChallengePool } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
18
20
  import { KEYSTONE_VERB_MANAGE, POOL_ID_MANAGE } from '@ibgib/core-gib/dist/keystone/keystone-constants.mjs';
@@ -28,35 +30,28 @@ import { bootstrapDomainMetaspace } from '../../../bootstrap-helper.mjs';
28
30
  import { getIdentityIndexService } from '../../../identity-index/identity-index-service.mjs';
29
31
  import { normalizeEmail } from '../../../identity-index/identity-index-helpers.mjs';
30
32
  import { loadSsoServerConfig } from '../../../../identity/sso/sso-config-helper.mjs';
31
- import { SsoCustodianService } from '../../../../identity/sso/sso-custodian-service.mjs';
33
+ import { getSsoCustodianService } from '../../../../identity/sso/sso-custodian-service.mjs';
32
34
  import { SsoProviderId } from '../../../../identity/sso/sso-types.mjs';
33
35
  import { getPendingStagingDir, getPendingTjpHash, verifyPendingCode } from '../../../../email/verify/email-verify-helpers.mjs';
34
36
 
35
37
  const logalot = GLOBAL_LOG_A_LOT || true;
36
38
 
37
- let custodian: SsoCustodianService | undefined;
38
- function getCustodian(): SsoCustodianService {
39
- if (!custodian) {
40
- const config = loadSsoServerConfig();
41
- custodian = new SsoCustodianService(config);
42
- }
43
- return custodian;
44
- }
45
-
46
39
  export interface CustodianAddMasterPasswordRequestBody {
47
- primaryTjpAddr: string;
48
- newManagePool: KeystoneChallengePool;
40
+ code: string;
49
41
  providerId?: SsoProviderId;
50
- code?: string;
51
42
  redirectUri?: string;
52
43
  email?: string;
44
+ primaryTjpAddr: string;
45
+ newManagePool: KeystoneChallengePool;
53
46
  }
54
47
 
55
48
  export interface CustodianAddMasterPasswordResponseBody {
56
49
  success: boolean;
57
- primaryTjpAddr: string;
58
- primaryKeystone: any;
50
+ primaryTjpAddr?: string;
51
+ primaryKeystone?: any;
52
+ primaryGraph?: FlatIbGibGraph;
59
53
  message?: string;
54
+ error?: string;
60
55
  }
61
56
 
62
57
  /**
@@ -108,7 +103,7 @@ export class KeystoneCustodianAddMasterPasswordHandler extends ServeGibHandlerBa
108
103
  let effectiveProvider: string = providerId || 'email';
109
104
 
110
105
  if (providerId && code && redirectUri) {
111
- const service = getCustodian();
106
+ const service = getSsoCustodianService();
112
107
  const userInfo = await service.getOAuthUserInfo(providerId, code, redirectUri);
113
108
  if (!userInfo || !userInfo.email) {
114
109
  return this.error(401, `Failed to authenticate with SSO provider ${providerId} (E: 8a1b2c3d4e5f67890a1b2c3d4e5f6796)`);
@@ -121,7 +116,11 @@ export class KeystoneCustodianAddMasterPasswordHandler extends ServeGibHandlerBa
121
116
  verifiedEmail = normalizeEmail(email);
122
117
 
123
118
  const tjpHash = await getPendingTjpHash(primaryTjpAddr);
124
- const pendingInfo = reqCtx.dataDir && tjpHash ? await getPendingStagingDir({ dataDir: reqCtx.dataDir, tjpHash }) : undefined;
119
+ let pendingInfo = reqCtx.dataDir && tjpHash ? await getPendingStagingDir({ dataDir: reqCtx.dataDir, tjpHash }) : undefined;
120
+ if (!pendingInfo) {
121
+ const emailTjpHash = await getPendingTjpHash(`pending:${verifiedEmail}`);
122
+ pendingInfo = reqCtx.dataDir && emailTjpHash ? await getPendingStagingDir({ dataDir: reqCtx.dataDir, tjpHash: emailTjpHash }) : undefined;
123
+ }
125
124
 
126
125
  if (!pendingInfo || pendingInfo.isExpired) {
127
126
  return this.error(400, 'Verification record missing or expired. Please request a new verification code. (E: 8a1b2c3d4e5f67890a1b2c3d4e5f6798)');
@@ -228,10 +227,18 @@ export class KeystoneCustodianAddMasterPasswordHandler extends ServeGibHandlerBa
228
227
  await metaspace.put({ ibGibs: [evolvedKeystone], space });
229
228
  await metaspace.registerNewIbGib({ ibGib: evolvedKeystone, space });
230
229
 
230
+ // Extract complete primary keystone dependency graph across all frames
231
+ const primaryGraph = await getDependencyGraph({
232
+ ibGib: evolvedKeystone,
233
+ space,
234
+ live: false
235
+ });
236
+
231
237
  const response: CustodianAddMasterPasswordResponseBody = {
232
238
  success: true,
233
239
  primaryTjpAddr,
234
240
  primaryKeystone: evolvedKeystone,
241
+ primaryGraph,
235
242
  message: 'Successfully elevated identity to sovereign master password'
236
243
  };
237
244
 
@@ -162,15 +162,20 @@ export class KeystoneCustodianRegisterDelegateHandler extends ServeGibHandlerBas
162
162
 
163
163
  const primarySecret = await hash({ s: `${serverSecret}_custodian_${primaryEmail}` });
164
164
 
165
+ const delegateDeviceName = delegateKeystone.data?.frameDetails?.deviceTag
166
+ || frameDetails?.deviceTag
167
+ || 'client-delegate';
168
+
165
169
  // Execute primary keystone evolution linking the new delegate
166
170
  const evolvedPrimaryKeystone = await keystoneService.registerDelegate({
167
171
  parentKeystone,
168
172
  delegateKeystone,
169
173
  masterSecret: primarySecret,
174
+ signingPoolId: 'manage',
170
175
  metaspace,
171
176
  space,
172
177
  allowedVerbs: custodianReqs.allowedVerbs || [KEYSTONE_VERB_SYNC, KEYSTONE_VERB_CONNECT],
173
- deviceName: frameDetails?.deviceTag || 'client-delegate'
178
+ deviceName: delegateDeviceName
174
179
  });
175
180
 
176
181
  // Persist delegate keystone in domain space
@@ -12,6 +12,7 @@
12
12
 
13
13
  import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
14
14
  import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
15
+ import { getGibInfo } from '@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs';
15
16
  import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
16
17
  import { validateAndRegisterEvolveKeystone } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs';
17
18
  import { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
@@ -56,7 +57,11 @@ export class KeystoneEvolveHandler extends ServeGibHandlerWithMetaspaceBase<Evol
56
57
  if (match && match.length >= 3) {
57
58
  const domainIb = decodeURIComponent(match[1]);
58
59
  const domainGib = decodeURIComponent(match[2]);
59
- const domainAddr = getIbGibAddr({ ib: domainIb, gib: domainGib });
60
+ let domainAddr = getIbGibAddr({ ib: domainIb, gib: domainGib });
61
+ const { tjpGib } = getGibInfo({ ibGibAddr: domainAddr });
62
+ if (tjpGib && domainIb) {
63
+ domainAddr = `${domainIb}^${tjpGib}`;
64
+ }
60
65
  return {
61
66
  domainAddr,
62
67
  domainInfo: this.getDomainInfo({ domainAddr })
@@ -1,6 +1,5 @@
1
1
  import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
2
- import { loadSsoServerConfig } from '../../../../identity/sso/sso-config-helper.mjs';
3
- import { SsoCustodianService } from '../../../../identity/sso/sso-custodian-service.mjs';
2
+ import { getSsoCustodianService } from '../../../../identity/sso/sso-custodian-service.mjs';
4
3
 
5
4
  import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
6
5
  import { ServeGibHandlerBase } from '../../handler-base.mjs';
@@ -9,15 +8,6 @@ import { RequestContext, ResponseResult, ServeGibHttpMethod } from '../../../typ
9
8
 
10
9
  const logalot = GLOBAL_LOG_A_LOT;
11
10
 
12
- let custodian: SsoCustodianService | undefined;
13
- function getCustodian(): SsoCustodianService {
14
- if (!custodian) {
15
- const config = loadSsoServerConfig();
16
- custodian = new SsoCustodianService(config);
17
- }
18
- return custodian;
19
- }
20
-
21
11
  /**
22
12
  * GET /api/identity/sso/config
23
13
  *
@@ -46,7 +36,7 @@ export class SsoConfigHandler extends ServeGibHandlerBase<any, any> {
46
36
  try {
47
37
  if (logalot) { console.log(`${lc} starting...`); }
48
38
 
49
- const service = getCustodian();
39
+ const service = getSsoCustodianService();
50
40
  const hostUrl = `${reqCtx.protocol}://${reqCtx.headers.host}`;
51
41
  const providers = service.getSsoClientConfigs(hostUrl);
52
42