@ibgib/web-gib 0.0.58 → 0.0.60

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 (54) hide show
  1. package/dist/AUTO-GENERATED-version.d.mts +1 -1
  2. package/dist/AUTO-GENERATED-version.mjs +1 -1
  3. package/dist/identity/custodian-delegate-helper.d.mts.map +1 -1
  4. package/dist/identity/custodian-delegate-helper.mjs +20 -3
  5. package/dist/identity/custodian-delegate-helper.mjs.map +1 -1
  6. package/dist/identity/identity-constants.mjs +2 -2
  7. package/dist/identity/identity-constants.mjs.map +1 -1
  8. package/dist/identity/identity-types.d.mts +4 -4
  9. package/dist/identity/identity-types.d.mts.map +1 -1
  10. package/dist/ui/component/identity/add-device/add-device.css +93 -17
  11. package/dist/ui/component/identity/add-device/add-device.d.mts +24 -7
  12. package/dist/ui/component/identity/add-device/add-device.d.mts.map +1 -1
  13. package/dist/ui/component/identity/add-device/add-device.html +97 -23
  14. package/dist/ui/component/identity/add-device/add-device.mjs +492 -184
  15. package/dist/ui/component/identity/add-device/add-device.mjs.map +1 -1
  16. package/dist/ui/component/identity/keystone-creator/keystone-creator.d.mts.map +1 -1
  17. package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs +126 -74
  18. package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs.map +1 -1
  19. package/dist/ui/component/identity/keystone-details/keystone-details.css +1 -1
  20. package/dist/ui/component/identity/keystone-details/keystone-details.d.mts +8 -8
  21. package/dist/ui/component/identity/keystone-details/keystone-details.d.mts.map +1 -1
  22. package/dist/ui/component/identity/keystone-details/keystone-details.html +29 -20
  23. package/dist/ui/component/identity/keystone-details/keystone-details.mjs +51 -51
  24. package/dist/ui/component/identity/keystone-details/keystone-details.mjs.map +1 -1
  25. package/dist/ui/component/identity/remove-device/remove-device.d.mts +1 -1
  26. package/dist/ui/component/identity/remove-device/remove-device.d.mts.map +1 -1
  27. package/dist/ui/component/identity/remove-device/remove-device.html +3 -3
  28. package/dist/ui/component/identity/remove-device/remove-device.mjs +7 -7
  29. package/dist/ui/component/identity/remove-device/remove-device.mjs.map +1 -1
  30. package/dist/util/device-helper.d.mts +30 -0
  31. package/dist/util/device-helper.d.mts.map +1 -0
  32. package/dist/util/device-helper.mjs +90 -0
  33. package/dist/util/device-helper.mjs.map +1 -0
  34. package/dist/util/device-helper.respec.d.mts +2 -0
  35. package/dist/util/device-helper.respec.d.mts.map +1 -0
  36. package/dist/util/device-helper.respec.mjs +83 -0
  37. package/dist/util/device-helper.respec.mjs.map +1 -0
  38. package/package.json +3 -3
  39. package/src/AUTO-GENERATED-version.mts +1 -1
  40. package/src/identity/custodian-delegate-helper.mts +28 -3
  41. package/src/identity/identity-constants.mts +2 -2
  42. package/src/identity/identity-types.mts +4 -4
  43. package/src/ui/component/identity/add-device/add-device.css +93 -17
  44. package/src/ui/component/identity/add-device/add-device.html +97 -23
  45. package/src/ui/component/identity/add-device/add-device.mts +579 -192
  46. package/src/ui/component/identity/keystone-creator/keystone-creator.mts +135 -76
  47. package/src/ui/component/identity/keystone-details/keystone-details.css +1 -1
  48. package/src/ui/component/identity/keystone-details/keystone-details.html +29 -20
  49. package/src/ui/component/identity/keystone-details/keystone-details.mts +57 -57
  50. package/src/ui/component/identity/remove-device/remove-device.html +3 -3
  51. package/src/ui/component/identity/remove-device/remove-device.mts +8 -8
  52. package/src/util/device-helper.mts +104 -0
  53. package/src/util/device-helper.respec.mts +90 -0
  54. package/tools/auto-generated-agent-skills/skills/ibgib-implementation-plan/SKILL.md +3 -0
@@ -10,7 +10,7 @@ import { getGibInfo } from "@ibgib/ts-gib/dist/V1/transforms/transform-helper.mj
10
10
  import { KeystoneService_V1 } from "@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs";
11
11
  import { KeystoneProfileBuilder } from "@ibgib/core-gib/dist/keystone/policy/keystone-profile-builder.mjs";
12
12
  import { updateSpecialIndex, } from "@ibgib/core-gib/dist/timeline/timeline-api.mjs";
13
- import { toDto, getTjpAddr } from "@ibgib/core-gib/dist/common/other/ibgib-helper.mjs";
13
+ import { toDto, getTjpAddr, getTimelinesGroupedByTjp } from "@ibgib/core-gib/dist/common/other/ibgib-helper.mjs";
14
14
  import { FlatIbGibGraph } from "@ibgib/core-gib/dist/common/other/graph-types.mjs";
15
15
  import { validateEmail } from "@ibgib/core-gib/dist/keystone/keystone-helpers.mjs";
16
16
  import { KEYSTONE_USERNAME_REGEXP, KEYSTONE_DESCRIPTION_REGEXP, KEYSTONE_VERB_SYNC, KEYSTONE_VERB_CONNECT } from "@ibgib/core-gib/dist/keystone/keystone-constants.mjs";
@@ -261,77 +261,119 @@ export class KeystoneCreatorComponentInstance
261
261
  */
262
262
  protected async handleSsoClick(providerId: 'google' | 'github'): Promise<void> {
263
263
  const lc = `${this.lc}[${this.handleSsoClick.name}]`;
264
- this.setStatus(`Opening ${providerId.toUpperCase()} SSO authorization window...`, 'info');
265
- const resPopup = await executeSsoOAuthPopup({ providerId });
266
- if (!resPopup.success || !resPopup.code) {
267
- this.setStatus(resPopup.message || `${providerId.toUpperCase()} sign-in cancelled.`, 'error');
268
- return;
269
- }
264
+ const providerName = providerId === 'google' ? 'Google' : providerId === 'github' ? 'GitHub' : providerId;
270
265
 
271
- this.setStatus(`Exchanging ${providerId.toUpperCase()} authorization code...`, 'info');
272
- const apiBridge = getApiBridge();
273
- const resLogin = await apiBridge.postSsoLogin({
274
- code: resPopup.code,
275
- providerId,
276
- redirectUri: resPopup.redirectUri!
266
+ this.setStatus(`Opening ${providerName} SSO authorization window...`, 'info');
267
+ this.showBusy({
268
+ isBusy: true,
269
+ title: `Connecting to ${providerName}...`,
270
+ msg: `Opening ${providerName} SSO authorization window...\nPlease complete authorization in the popup window.`,
271
+ animationEmoji: '🌐'
277
272
  });
278
273
 
279
- if (!resLogin.success || !resLogin.primaryTjpAddr || !resLogin.custodianReqs) {
280
- this.setStatus(resLogin.message || `${providerId.toUpperCase()} login failed.`, 'error');
281
- return;
282
- }
274
+ try {
275
+ const resPopup = await executeSsoOAuthPopup({ providerId });
276
+ if (!resPopup.success || !resPopup.code) {
277
+ this.setStatus(resPopup.message || `${providerName} sign-in cancelled.`, 'error');
278
+ return;
279
+ }
283
280
 
284
- const { primaryTjpAddr, custodianReqs } = resLogin;
285
- this.setStatus('Deriving local device delegate keys...', 'info');
286
- const delegateSecret = await deriveLocalCustodianDelegateSecret({ primaryTjpAddr });
287
- const email = resLogin.userInfo?.email || '';
288
- const username = email ? email.split('@')[0] : 'user';
281
+ this.setStatus(`Exchanging ${providerName} authorization code...`, 'info');
282
+ this.showBusy({
283
+ isBusy: true,
284
+ title: 'Exchanging SSO Code...',
285
+ msg: `Validating ${providerName} authorization code with custodian server...`,
286
+ animationEmoji: '🔐'
287
+ });
289
288
 
290
- const delegateBuilder = KeystoneProfileBuilder.buildKeystone('sync')
291
- .withUsername(`${username}-sync`)
292
- .withDescription(`Sync Delegate for ${username}`)
293
- .withDetails({
294
- client: 'space-gib-web',
295
- role: 'sync-delegate',
296
- primaryTjpAddr,
297
- custodianReqs,
289
+ const apiBridge = getApiBridge();
290
+ const resLogin = await apiBridge.postSsoLogin({
291
+ code: resPopup.code,
292
+ providerId,
293
+ redirectUri: resPopup.redirectUri!
298
294
  });
299
295
 
300
- const configs = await delegateBuilder.compileConfigs();
301
- const metaspace = await getGlobalMetaspace_waitIfNeeded();
302
- const space = await metaspace.getLocalUserSpace({ lock: false });
303
- if (!space) {
304
- this.setStatus('Could not access local user space.', 'error');
305
- return;
306
- }
296
+ if (!resLogin.success || !resLogin.primaryTjpAddr || !resLogin.custodianReqs) {
297
+ this.setStatus(resLogin.message || `${providerName} login failed.`, 'error');
298
+ return;
299
+ }
307
300
 
308
- const keystoneService = new KeystoneService_V1();
309
- const delegateKeystone = await keystoneService.genesis({
310
- masterSecret: delegateSecret,
311
- configs,
312
- metaspace,
313
- space,
314
- frameDetails: delegateBuilder.getFrameDetails(),
315
- isPrimary: false
316
- });
301
+ const { primaryTjpAddr, custodianReqs } = resLogin;
302
+ this.setStatus('Deriving local device delegate keys...', 'info');
303
+ this.showBusy({
304
+ isBusy: true,
305
+ title: 'Creating Sync Delegate...',
306
+ msg: 'Generating cryptographic sync delegate keys...',
307
+ animationEmoji: '🔑'
308
+ });
317
309
 
318
- this.setStatus('Registering device delegate with custodian server...', 'info');
319
- const resRegister = await apiBridge.postCustodianRegisterDelegate({ delegateKeystone });
310
+ const delegateSecret = await deriveLocalCustodianDelegateSecret({ primaryTjpAddr });
311
+ const email = resLogin.userInfo?.email || '';
312
+ const username = email ? email.split('@')[0] : 'user';
313
+ const custodianSyncProfileName = process.env.KEYSTONE_PROFILE_CUSTODIAN_SYNC;
314
+ if (!custodianSyncProfileName || !custodianSyncProfileName.trim()) {
315
+ throw new Error('KEYSTONE_PROFILE_CUSTODIAN_SYNC environment variable is missing. Expected valid profile name like "sync-profile.dev" or "sync-profile.prod". (E: 4d5e6f7890123456789abcdef4)');
316
+ }
320
317
 
321
- if (!resRegister.success) {
322
- this.setStatus(resRegister.message || 'Custodian delegate registration failed.', 'error');
323
- return;
324
- }
318
+ const delegateBuilder = KeystoneProfileBuilder.buildKeystone(custodianSyncProfileName.trim() as any)
319
+ .withUsername(`${username}-sync`)
320
+ .withDescription(`Sync Delegate for ${username}`)
321
+ .withDetails({
322
+ client: 'space-gib-web',
323
+ role: 'sync-delegate',
324
+ primaryTjpAddr,
325
+ custodianReqs,
326
+ });
325
327
 
326
- // Finalize onboarding: update keystones index, activate identity, and navigate to identity manager
327
- await this.finalizeIdentityOnboarding({
328
- primaryKeystone: resRegister.evolvedPrimaryKeystone || resLogin.primaryKeystone,
329
- primaryGraph: resRegister.primaryGraph || resLogin.primaryGraph,
330
- delegateKeystone,
331
- primaryTjpAddr,
332
- delegateSecret,
333
- makeActive: true
334
- });
328
+ const configs = await delegateBuilder.compileConfigs();
329
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
330
+ const space = await metaspace.getLocalUserSpace({ lock: false });
331
+ if (!space) {
332
+ this.setStatus('Could not access local user space.', 'error');
333
+ return;
334
+ }
335
+
336
+ const keystoneService = new KeystoneService_V1();
337
+ const delegateKeystone = await keystoneService.genesis({
338
+ masterSecret: delegateSecret,
339
+ configs,
340
+ metaspace,
341
+ space,
342
+ frameDetails: delegateBuilder.getFrameDetails(),
343
+ isPrimary: false
344
+ });
345
+
346
+ this.setStatus('Registering device delegate with custodian server...', 'info');
347
+ this.showBusy({
348
+ isBusy: true,
349
+ title: 'Registering Delegate...',
350
+ msg: 'Registering local delegate with custodian server...',
351
+ animationEmoji: '📝'
352
+ });
353
+
354
+ const resRegister = await apiBridge.postCustodianRegisterDelegate({ delegateKeystone });
355
+ if (!resRegister.success) {
356
+ this.setStatus(resRegister.message || 'Custodian delegate registration failed.', 'error');
357
+ return;
358
+ }
359
+
360
+ // Finalize onboarding: update keystones index, activate identity, and navigate to identity manager
361
+ await this.finalizeIdentityOnboarding({
362
+ primaryKeystone: resRegister.evolvedPrimaryKeystone || resLogin.primaryKeystone,
363
+ primaryGraph: resRegister.primaryGraph || resLogin.primaryGraph,
364
+ delegateKeystone,
365
+ primaryTjpAddr,
366
+ delegateSecret,
367
+ makeActive: true
368
+ });
369
+
370
+ } catch (error) {
371
+ const emsg = extractErrorMsg(error);
372
+ console.error(`${lc} ${emsg}`, error);
373
+ this.setStatus(`SSO sign-in error: ${emsg}`, 'error');
374
+ } finally {
375
+ this.showBusy({ isBusy: false });
376
+ }
335
377
  }
336
378
 
337
379
  /**
@@ -426,8 +468,13 @@ export class KeystoneCreatorComponentInstance
426
468
  });
427
469
 
428
470
  const delegateSecret = await deriveLocalCustodianDelegateSecret({ primaryTjpAddr });
429
- const username = email.split('@')[0];
430
- const delegateBuilder = KeystoneProfileBuilder.buildKeystone('sync')
471
+ const username = email ? email.split('@')[0] : 'user';
472
+ const custodianSyncProfileName = process.env.KEYSTONE_PROFILE_CUSTODIAN_SYNC;
473
+ if (!custodianSyncProfileName || !custodianSyncProfileName.trim()) {
474
+ throw new Error('KEYSTONE_PROFILE_CUSTODIAN_SYNC environment variable is missing. Expected valid profile name like "sync-profile.dev" or "sync-profile.prod". (E: 4d5e6f7890123456789abcdef4)');
475
+ }
476
+
477
+ const delegateBuilder = KeystoneProfileBuilder.buildKeystone(custodianSyncProfileName.trim() as any)
431
478
  .withUsername(`${username}-sync`)
432
479
  .withDescription(`Sync Delegate for ${username}`)
433
480
  .withDetails({
@@ -577,13 +624,14 @@ export class KeystoneCreatorComponentInstance
577
624
  animationEmoji: '⚙️'
578
625
  });
579
626
 
580
- // 1. Prepare Primary/Domain Keystone Configs
581
- const isProd = process.env.NODE_ENV === 'production';
582
- const requestedProfile = (process.env.KEYSTONE_PROFILE || 'domain').toLowerCase();
583
- const profileName = (isProd && requestedProfile === 'test') ? 'domain' : requestedProfile;
584
- console.log(`${lc} Using keystone policy profile '${profileName}' (I: 90123456789abcdef0123456789abcde)`);
627
+ // 1. Prepare Primary Keystone Configs
628
+ const sovereignPrimaryProfileName = process.env.KEYSTONE_PROFILE_SOVEREIGN_PRIMARY;
629
+ if (!sovereignPrimaryProfileName || !sovereignPrimaryProfileName.trim()) {
630
+ throw new Error('KEYSTONE_PROFILE_SOVEREIGN_PRIMARY environment variable is missing. Expected valid profile name like "primary-profile.dev" or "primary-profile.prod". (E: 3c4d5e6f7890123456789abcdef3)');
631
+ }
632
+ console.log(`${lc} Using sovereign primary keystone policy profile '${sovereignPrimaryProfileName}' (I: 90123456789abcdef0123456789abcde)`);
585
633
 
586
- const builder = KeystoneProfileBuilder.buildKeystone(profileName as any)
634
+ const builder = KeystoneProfileBuilder.buildKeystone(sovereignPrimaryProfileName.trim() as any)
587
635
  .withUsername(username)
588
636
  .withDescription(description);
589
637
  if (email) {
@@ -595,10 +643,13 @@ export class KeystoneCreatorComponentInstance
595
643
  });
596
644
  const configs = await builder.compileConfigs();
597
645
 
598
- // 2. Get local services
646
+ // 2. Prepare Metaspace/Space
599
647
  const metaspace = await getGlobalMetaspace_waitIfNeeded();
600
- const space = await metaspace.getLocalUserSpace({});
601
- if (!space) { throw new Error("No default space found in metaspace."); }
648
+ const space = await metaspace.getLocalUserSpace({ lock: false });
649
+ if (!space) {
650
+ this.setStatus("Failed to access local user space.", "error");
651
+ return;
652
+ }
602
653
 
603
654
  // 3. Perform Genesis (Local)
604
655
  this.showBusy({
@@ -633,7 +684,12 @@ export class KeystoneCreatorComponentInstance
633
684
  });
634
685
 
635
686
  const delegateSecret = await deriveDelegateSecret({ masterSecret });
636
- const delegateBuilder = KeystoneProfileBuilder.buildKeystone(profileName as any)
687
+ const sovereignSyncProfileName = process.env.KEYSTONE_PROFILE_SOVEREIGN_SYNC;
688
+ if (!sovereignSyncProfileName || !sovereignSyncProfileName.trim()) {
689
+ throw new Error('KEYSTONE_PROFILE_SOVEREIGN_SYNC environment variable is missing. Expected valid profile name like "sync-profile.dev" or "sync-profile.prod". (E: 5e6f7890123456789abcdef5)');
690
+ }
691
+
692
+ const delegateBuilder = KeystoneProfileBuilder.buildKeystone(sovereignSyncProfileName.trim() as any)
637
693
  .withUsername(`${username}-sync`)
638
694
  .withDescription(`Sync Delegate for ${username}`)
639
695
  .withDetails({
@@ -865,9 +921,12 @@ export class KeystoneCreatorComponentInstance
865
921
  // 0. Persist all frames of primary identity graph into local browser space
866
922
  if (primaryGraph) {
867
923
  const graphIbGibs = Object.values(primaryGraph) as IbGib_V1[];
868
- for (const frame of graphIbGibs) {
869
- await metaspace.put({ ibGibs: [frame], space });
870
- await metaspace.registerNewIbGib({ ibGib: frame, space });
924
+ await metaspace.put({ ibGibs: graphIbGibs, space });
925
+ const timelinesMap = getTimelinesGroupedByTjp({ ibGibs: graphIbGibs });
926
+ for (const tjpKey of Object.keys(timelinesMap)) {
927
+ for (const frame of timelinesMap[tjpKey]) {
928
+ await metaspace.registerNewIbGib({ ibGib: frame, space });
929
+ }
871
930
  }
872
931
  } else if (primaryKeystone) {
873
932
  await metaspace.put({ ibGibs: [primaryKeystone], space });
@@ -578,7 +578,7 @@
578
578
  opacity: 0.4;
579
579
  }
580
580
 
581
- /* Form Layout for Passphrase Rotation */
581
+ /* Form Layout for Password Rotation */
582
582
  .form-row {
583
583
  display: flex;
584
584
  gap: 1rem;
@@ -60,7 +60,8 @@
60
60
  <div id="delegates-card" class="card">
61
61
  <h3>Registered Delegates</h3>
62
62
  <div id="delegates-container" class="delegates-container">
63
- <p class="description">Active sub-keystones authorized to perform sync and operations on behalf of this Domain Identity.</p>
63
+ <p class="description">Active sub-keystones authorized to perform operations on behalf of this Domain
64
+ Identity.</p>
64
65
  <table class="delegates-table">
65
66
  <thead>
66
67
  <tr>
@@ -80,7 +81,8 @@
80
81
  <!-- SSO Identity Linking Card -->
81
82
  <div id="sso-link-card" class="card hidden">
82
83
  <h3>Identity Providers</h3>
83
- <p class="description">Securely link or unlink external OAuth2 providers to delegate sync access to this identity.</p>
84
+ <p class="description">Securely link or unlink external OAuth2 providers to delegate sync access to this
85
+ identity.</p>
84
86
  <div class="sso-toggle-group">
85
87
  <!-- Google Card Toggle -->
86
88
  <div id="btn-link-google" class="sso-toggle-card google" role="button" tabindex="0">
@@ -88,10 +90,14 @@
88
90
  <div class="toggle-content">
89
91
  <!-- Custom Google SVG Icon -->
90
92
  <svg class="sso-icon" viewBox="0 0 24 24">
91
- <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
92
- <path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
93
- <path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.06H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.94l2.85-2.22.81-.63z"/>
94
- <path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.06l3.66 2.84c.87-2.6 3.3-4.52 6.16-4.52z"/>
93
+ <path fill="#4285F4"
94
+ d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" />
95
+ <path fill="#34A853"
96
+ d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" />
97
+ <path fill="#FBBC05"
98
+ d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.06H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.94l2.85-2.22.81-.63z" />
99
+ <path fill="#EA4335"
100
+ d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.06l3.66 2.84c.87-2.6 3.3-4.52 6.16-4.52z" />
95
101
  </svg>
96
102
  <span class="provider-label">Google</span>
97
103
  <span class="toggle-state-text">Unlinked</span>
@@ -105,7 +111,8 @@
105
111
  <div class="toggle-content">
106
112
  <!-- Custom GitHub SVG Icon -->
107
113
  <svg class="sso-icon" viewBox="0 0 24 24" fill="currentColor">
108
- <path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
114
+ <path
115
+ d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
109
116
  </svg>
110
117
  <span class="provider-label">GitHub</span>
111
118
  <span class="toggle-state-text">Unlinked</span>
@@ -116,28 +123,30 @@
116
123
  <div id="sso-status-msg" class="status-msg hidden"></div>
117
124
  </div>
118
125
 
119
- <!-- Change Passphrase Card -->
120
- <div id="change-passphrase-card" class="card">
121
- <h3>Change Master Passphrase</h3>
122
- <p class="description">Rotate your local master passphrase. This will cryptographically evolve your primary identity and all registered user-owned delegate keystones to the new passphrase.</p>
126
+ <!-- Change Password Card -->
127
+ <div id="change-password-card" class="card">
128
+ <h3>Change Password</h3>
129
+ <p class="description">Rotate your local password that drives this identity. This will cryptographically
130
+ evolve your primary
131
+ identity and all registered user-owned delegate keystones to the new password.</p>
123
132
  <div class="form-row">
124
133
  <div class="form-group">
125
- <label for="input-current-passphrase">Current Passphrase</label>
126
- <input type="password" id="input-current-passphrase" placeholder="••••••••" class="form-input">
134
+ <label for="input-current-password">Current Password</label>
135
+ <input type="password" id="input-current-password" placeholder="••••••••" class="form-input">
127
136
  </div>
128
137
  <div class="form-group">
129
- <label for="input-new-passphrase">New Passphrase</label>
130
- <input type="password" id="input-new-passphrase" placeholder="••••••••" class="form-input">
138
+ <label for="input-new-password">New Password</label>
139
+ <input type="password" id="input-new-password" placeholder="••••••••" class="form-input">
131
140
  </div>
132
141
  <div class="form-group">
133
- <label for="input-confirm-passphrase">Confirm New Passphrase</label>
134
- <input type="password" id="input-confirm-passphrase" placeholder="••••••••" class="form-input">
142
+ <label for="input-confirm-password">Confirm New Password</label>
143
+ <input type="password" id="input-confirm-password" placeholder="••••••••" class="form-input">
135
144
  </div>
136
145
  </div>
137
146
  <div class="action-row">
138
- <button id="btn-change-passphrase" class="action-btn">Update Passphrase</button>
147
+ <button id="btn-change-password" class="action-btn">Update Password</button>
139
148
  </div>
140
- <div id="change-passphrase-status" class="status-msg hidden"></div>
149
+ <div id="change-password-status" class="status-msg hidden"></div>
141
150
  </div>
142
151
 
143
152
  <!-- Raw Keystone Timeline Explorer -->
@@ -151,4 +160,4 @@
151
160
  </div>
152
161
  </div>
153
162
  </div>
154
- </div>
163
+ </div>