@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.
- package/dist/AUTO-GENERATED-version.d.mts +1 -1
- package/dist/AUTO-GENERATED-version.mjs +1 -1
- package/dist/identity/custodian-delegate-helper.d.mts.map +1 -1
- package/dist/identity/custodian-delegate-helper.mjs +20 -3
- package/dist/identity/custodian-delegate-helper.mjs.map +1 -1
- package/dist/identity/identity-constants.mjs +2 -2
- package/dist/identity/identity-constants.mjs.map +1 -1
- package/dist/identity/identity-types.d.mts +4 -4
- package/dist/identity/identity-types.d.mts.map +1 -1
- package/dist/ui/component/identity/add-device/add-device.css +93 -17
- package/dist/ui/component/identity/add-device/add-device.d.mts +24 -7
- package/dist/ui/component/identity/add-device/add-device.d.mts.map +1 -1
- package/dist/ui/component/identity/add-device/add-device.html +97 -23
- package/dist/ui/component/identity/add-device/add-device.mjs +492 -184
- package/dist/ui/component/identity/add-device/add-device.mjs.map +1 -1
- package/dist/ui/component/identity/keystone-creator/keystone-creator.d.mts.map +1 -1
- package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs +126 -74
- package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs.map +1 -1
- package/dist/ui/component/identity/keystone-details/keystone-details.css +1 -1
- package/dist/ui/component/identity/keystone-details/keystone-details.d.mts +8 -8
- package/dist/ui/component/identity/keystone-details/keystone-details.d.mts.map +1 -1
- package/dist/ui/component/identity/keystone-details/keystone-details.html +29 -20
- package/dist/ui/component/identity/keystone-details/keystone-details.mjs +51 -51
- package/dist/ui/component/identity/keystone-details/keystone-details.mjs.map +1 -1
- package/dist/ui/component/identity/remove-device/remove-device.d.mts +1 -1
- package/dist/ui/component/identity/remove-device/remove-device.d.mts.map +1 -1
- package/dist/ui/component/identity/remove-device/remove-device.html +3 -3
- package/dist/ui/component/identity/remove-device/remove-device.mjs +7 -7
- package/dist/ui/component/identity/remove-device/remove-device.mjs.map +1 -1
- package/dist/util/device-helper.d.mts +30 -0
- package/dist/util/device-helper.d.mts.map +1 -0
- package/dist/util/device-helper.mjs +90 -0
- package/dist/util/device-helper.mjs.map +1 -0
- package/dist/util/device-helper.respec.d.mts +2 -0
- package/dist/util/device-helper.respec.d.mts.map +1 -0
- package/dist/util/device-helper.respec.mjs +83 -0
- package/dist/util/device-helper.respec.mjs.map +1 -0
- package/package.json +3 -3
- package/src/AUTO-GENERATED-version.mts +1 -1
- package/src/identity/custodian-delegate-helper.mts +28 -3
- package/src/identity/identity-constants.mts +2 -2
- package/src/identity/identity-types.mts +4 -4
- package/src/ui/component/identity/add-device/add-device.css +93 -17
- package/src/ui/component/identity/add-device/add-device.html +97 -23
- package/src/ui/component/identity/add-device/add-device.mts +579 -192
- package/src/ui/component/identity/keystone-creator/keystone-creator.mts +135 -76
- package/src/ui/component/identity/keystone-details/keystone-details.css +1 -1
- package/src/ui/component/identity/keystone-details/keystone-details.html +29 -20
- package/src/ui/component/identity/keystone-details/keystone-details.mts +57 -57
- package/src/ui/component/identity/remove-device/remove-device.html +3 -3
- package/src/ui/component/identity/remove-device/remove-device.mts +8 -8
- package/src/util/device-helper.mts +104 -0
- package/src/util/device-helper.respec.mts +90 -0
- 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
|
-
|
|
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(`
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
-
|
|
291
|
-
.
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
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
|
-
|
|
319
|
-
|
|
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
|
-
|
|
322
|
-
|
|
323
|
-
|
|
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
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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
|
|
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
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
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(
|
|
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.
|
|
646
|
+
// 2. Prepare Metaspace/Space
|
|
599
647
|
const metaspace = await getGlobalMetaspace_waitIfNeeded();
|
|
600
|
-
const space = await metaspace.getLocalUserSpace({});
|
|
601
|
-
if (!space) {
|
|
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
|
|
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
|
-
|
|
869
|
-
|
|
870
|
-
|
|
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 });
|
|
@@ -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
|
|
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
|
|
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"
|
|
92
|
-
|
|
93
|
-
<path fill="#
|
|
94
|
-
|
|
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
|
|
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
|
|
120
|
-
<div id="change-
|
|
121
|
-
<h3>Change
|
|
122
|
-
<p class="description">Rotate your local
|
|
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-
|
|
126
|
-
<input type="password" id="input-current-
|
|
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-
|
|
130
|
-
<input type="password" id="input-new-
|
|
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-
|
|
134
|
-
<input type="password" id="input-confirm-
|
|
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-
|
|
147
|
+
<button id="btn-change-password" class="action-btn">Update Password</button>
|
|
139
148
|
</div>
|
|
140
|
-
<div id="change-
|
|
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>
|