@ibgib/space-gib 0.0.7 → 0.0.9

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibgib/space-gib",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "description": "ibgib storage and provider service — SaaS at ibgib.space",
6
6
  "scripts": {
@@ -12,11 +12,11 @@
12
12
  "build:test": "tsc -p tsconfig.test.json"
13
13
  },
14
14
  "dependencies": {
15
- "@ibgib/core-gib": "^0.1.64",
15
+ "@ibgib/core-gib": "^0.1.66",
16
16
  "@ibgib/helper-gib": "^0.0.36",
17
17
  "@ibgib/ts-gib": "^0.5.33",
18
- "@ibgib/web-gib": "^0.0.50",
19
- "@ibgib/node-gib": "^0.0.8"
18
+ "@ibgib/web-gib": "^0.0.52",
19
+ "@ibgib/node-gib": "^0.0.10"
20
20
  },
21
21
  "engines": {
22
22
  "node": ">=20.0.0"
@@ -8,4 +8,4 @@
8
8
  /**
9
9
  * Version of space-gib, auto-updated by the build process.
10
10
  */
11
- export const AUTO_GENERATED_VERSION = '0.0.7';
11
+ export const AUTO_GENERATED_VERSION = '0.0.9';
@@ -51,9 +51,39 @@ export class SpaceGibApiBridge {
51
51
  }
52
52
 
53
53
  /**
54
- * PUTs an evolved domain keystone and any related ibgibs (e.g. S^Stjp) to the server.
54
+ * PUTs an evolved domain keystone and any related keystones (e.g., session
55
+ * keystones or delegate keystones) to the server.
55
56
  */
56
- public async putEvolveKeystone(domainAddr: string, keystoneIbGib: IbGib_V1, relatedIbGibs: IbGib_V1[] = []): Promise<{ success: boolean; message?: string }> {
57
+ public async putEvolveKeystone({
58
+ domainAddr,
59
+ keystoneIbGib,
60
+ relatedKeystoneIbGibs = [],
61
+ revokeTokens
62
+ }: {
63
+ /**
64
+ * Address of the root parent domain identity keystone.
65
+ */
66
+ domainAddr: string;
67
+ /**
68
+ * The main evolved keystone frame being synchronized.
69
+ */
70
+ keystoneIbGib: IbGib_V1;
71
+ /**
72
+ * Array of other keystone frames related to this evolution.
73
+ * Distinction in intent:
74
+ * 1. Ephemeral Session Keystones: Temporary keystones generated to
75
+ * authorize a single sync session (under 'sync' claims, targeted via
76
+ * claim.target = sAddr).
77
+ * 2. Persistent Delegate Keystones: Long-lived sub-keystones registered
78
+ * in the parent's `delegates` dictionary that are evolved
79
+ * concurrently (e.g., during 'manage' password changes).
80
+ */
81
+ relatedKeystoneIbGibs?: IbGib_V1[];
82
+ /**
83
+ * Optional map of providerId to token to revoke during unlinking.
84
+ */
85
+ revokeTokens?: Record<string, string>;
86
+ }): Promise<{ success: boolean; message?: string }> {
57
87
  const lc = `${this.lc}[${this.putEvolveKeystone.name}]`;
58
88
  try {
59
89
  console.log(`${lc} posting evolved keystone...`);
@@ -65,7 +95,11 @@ export class SpaceGibApiBridge {
65
95
  headers: {
66
96
  'Content-Type': 'application/json',
67
97
  },
68
- body: JSON.stringify({ keystoneIbGib, relatedIbGibs }),
98
+ body: JSON.stringify({
99
+ keystoneIbGib,
100
+ relatedKeystoneIbGibs,
101
+ revokeTokens
102
+ }),
69
103
  });
70
104
 
71
105
  const data = await response.json();
@@ -363,11 +363,11 @@ export class KeystoneCreatorComponentInstance
363
363
  msg: 'Posting evolved domain identity and sync delegate to server...',
364
364
  animationEmoji: '🔄'
365
365
  });
366
- const resEvolve = await spaceGibApiBridge.putEvolveKeystone(
367
- addr,
368
- evolvedParentKeystoneIbGib,
369
- [delegateKeystoneIbGib]
370
- );
366
+ const resEvolve = await spaceGibApiBridge.putEvolveKeystone({
367
+ domainAddr: addr,
368
+ keystoneIbGib: evolvedParentKeystoneIbGib,
369
+ relatedKeystoneIbGibs: [delegateKeystoneIbGib]
370
+ });
371
371
  if (!resEvolve.success) {
372
372
  this.setStatus(`Delegate registration sync failed: ${resEvolve.message}`, "error");
373
373
  devLog(`✗ Server rejected delegate registration: ${resEvolve.message}`);
@@ -433,40 +433,179 @@
433
433
  }
434
434
  }
435
435
 
436
- .sso-actions {
436
+ /* Grouped Toggle Switch for Identity Providers */
437
+ .sso-toggle-group {
437
438
  display: flex;
438
- gap: 1rem;
439
+ gap: 1.5rem;
439
440
  margin-top: 1rem;
440
441
  flex-wrap: wrap;
441
442
  }
442
443
 
443
- .sso-btn {
444
+ .sso-toggle-card {
444
445
  flex: 1;
445
- min-width: 200px;
446
- display: inline-flex;
447
- justify-content: center;
446
+ min-width: 180px;
447
+ max-width: 240px;
448
+ height: 180px;
449
+ background: rgba(255, 255, 255, 0.02);
450
+ border: 1px solid rgba(255, 255, 255, 0.06);
451
+ border-radius: var(--radius-md, 8px);
452
+ display: flex;
453
+ flex-direction: column;
454
+ justify-content: space-between;
448
455
  align-items: center;
449
- gap: 0.5rem;
450
- padding: 0.75rem 1.25rem;
456
+ cursor: pointer;
457
+ overflow: hidden;
458
+ position: relative;
459
+ user-select: none;
460
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
461
+ }
462
+
463
+ .sso-toggle-card:hover {
464
+ background: rgba(255, 255, 255, 0.04);
465
+ border-color: rgba(255, 255, 255, 0.12);
466
+ transform: translateY(-2px);
467
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
468
+ }
469
+
470
+ .sso-toggle-card:focus-visible {
471
+ outline: 2px solid var(--clr-accent, #50fa7b);
472
+ outline-offset: 2px;
473
+ }
474
+
475
+ /* Status Indicator bars: Top (Green/Active) and Bottom (Red/Faded) */
476
+ .toggle-status-indicator {
477
+ width: 100%;
478
+ height: 6px;
479
+ transition: all 0.25s ease-in-out;
480
+ }
481
+
482
+ .toggle-status-indicator.top {
483
+ background: transparent;
484
+ }
485
+
486
+ .toggle-status-indicator.bottom {
487
+ background: transparent;
488
+ }
489
+
490
+ /* Middle Content Wrapper */
491
+ .toggle-content {
492
+ display: flex;
493
+ flex-direction: column;
494
+ align-items: center;
495
+ justify-content: center;
496
+ gap: 0.6rem;
497
+ padding: 1rem;
498
+ text-align: center;
499
+ }
500
+
501
+ .sso-icon {
502
+ width: 2.25rem;
503
+ height: 2.25rem;
504
+ transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
505
+ }
506
+
507
+ .sso-toggle-card:hover .sso-icon {
508
+ transform: scale(1.1);
509
+ }
510
+
511
+ .provider-label {
512
+ font-size: 0.95rem;
451
513
  font-weight: 600;
514
+ color: var(--clr-text-primary, #ffffff);
452
515
  }
453
516
 
454
- .sso-btn.google {
455
- background: #4285F4;
456
- border-color: #4285F4;
457
- color: #ffffff;
517
+ .toggle-state-text {
518
+ font-size: 0.75rem;
519
+ font-weight: 500;
520
+ text-transform: uppercase;
521
+ letter-spacing: 0.05em;
522
+ color: var(--clr-text-secondary, #8fa08f);
523
+ transition: color 0.25s ease-in-out;
524
+ }
525
+
526
+ /* Linked (Active State) styles */
527
+ .sso-toggle-card.linked {
528
+ background: rgba(80, 250, 123, 0.02);
529
+ border-color: rgba(80, 250, 123, 0.2);
530
+ box-shadow: 0 4px 16px rgba(80, 250, 123, 0.04);
531
+ }
532
+
533
+ .sso-toggle-card.linked:hover {
534
+ background: rgba(80, 250, 123, 0.04);
535
+ border-color: rgba(80, 250, 123, 0.35);
536
+ }
537
+
538
+ .sso-toggle-card.linked .toggle-status-indicator.top {
539
+ background: var(--clr-accent, #50fa7b);
540
+ box-shadow: 0 2px 10px rgba(80, 250, 123, 0.5);
541
+ }
542
+
543
+ .sso-toggle-card.linked .toggle-state-text {
544
+ color: var(--clr-accent, #50fa7b);
545
+ font-weight: bold;
546
+ }
547
+
548
+ /* Unlinked (Inactive/Faded State) styles */
549
+ .sso-toggle-card.unlinked {
550
+ opacity: 0.75;
551
+ }
552
+
553
+ .sso-toggle-card.unlinked:hover {
554
+ opacity: 1.0;
555
+ }
556
+
557
+ .sso-toggle-card.unlinked .toggle-status-indicator.bottom {
558
+ background: rgba(255, 85, 85, 0.4);
559
+ }
560
+
561
+ .sso-toggle-card.unlinked .toggle-state-text {
562
+ color: var(--clr-text-secondary, #8fa08f);
563
+ }
564
+
565
+ /* Historical/Disabled state */
566
+ .sso-toggle-card.disabled {
567
+ pointer-events: none;
568
+ opacity: 0.4;
458
569
  }
459
570
 
460
- .sso-btn.google:hover {
461
- background: #357ae8;
571
+ /* Form Layout for Passphrase Rotation */
572
+ .form-row {
573
+ display: flex;
574
+ gap: 1rem;
575
+ flex-wrap: wrap;
576
+ margin-top: 0.5rem;
577
+ }
578
+
579
+ .form-group {
580
+ flex: 1;
581
+ min-width: 200px;
582
+ display: flex;
583
+ flex-direction: column;
584
+ gap: 0.4rem;
462
585
  }
463
586
 
464
- .sso-btn.github {
465
- background: #333333;
466
- border-color: #444444;
587
+ .form-group label {
588
+ font-size: 0.75rem;
589
+ font-weight: 600;
590
+ text-transform: uppercase;
591
+ letter-spacing: 0.03em;
592
+ color: var(--clr-text-secondary, #8fa08f);
593
+ }
594
+
595
+ .form-input {
596
+ padding: 0.65rem 0.8rem;
597
+ background: rgba(0, 0, 0, 0.35);
598
+ border: 1px solid var(--border-color-base, rgba(255, 255, 255, 0.08));
599
+ border-radius: var(--radius-sm, 6px);
467
600
  color: #ffffff;
601
+ font-family: var(--font-family-base, inherit);
602
+ font-size: 0.9rem;
603
+ transition: all 0.2s ease-in-out;
468
604
  }
469
605
 
470
- .sso-btn.github:hover {
471
- background: #444444;
606
+ .form-input:focus {
607
+ outline: none;
608
+ border-color: var(--clr-accent, #50fa7b);
609
+ background: rgba(0, 0, 0, 0.5);
610
+ box-shadow: 0 0 8px rgba(80, 250, 123, 0.15);
472
611
  }
@@ -76,15 +76,67 @@
76
76
 
77
77
  <!-- SSO Identity Linking Card -->
78
78
  <div id="sso-link-card" class="card hidden">
79
- <h3>Link Identity Provider</h3>
80
- <p class="description">Evolve this Domain Identity by linking a Web2 provider (Google, GitHub) to delegate sync access.</p>
81
- <div class="sso-actions">
82
- <button id="btn-link-google" class="action-btn sso-btn google">Link Google Account</button>
83
- <button id="btn-link-github" class="action-btn sso-btn github">Link GitHub Account</button>
79
+ <h3>Identity Providers</h3>
80
+ <p class="description">Securely link or unlink external OAuth2 providers to delegate sync access to this identity.</p>
81
+ <div class="sso-toggle-group">
82
+ <!-- Google Card Toggle -->
83
+ <div id="btn-link-google" class="sso-toggle-card google" role="button" tabindex="0">
84
+ <div class="toggle-status-indicator top"></div>
85
+ <div class="toggle-content">
86
+ <!-- Custom Google SVG Icon -->
87
+ <svg class="sso-icon" viewBox="0 0 24 24">
88
+ <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"/>
89
+ <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"/>
90
+ <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"/>
91
+ <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"/>
92
+ </svg>
93
+ <span class="provider-label">Google</span>
94
+ <span class="toggle-state-text">Unlinked</span>
95
+ </div>
96
+ <div class="toggle-status-indicator bottom"></div>
97
+ </div>
98
+
99
+ <!-- GitHub Card Toggle -->
100
+ <div id="btn-link-github" class="sso-toggle-card github" role="button" tabindex="0">
101
+ <div class="toggle-status-indicator top"></div>
102
+ <div class="toggle-content">
103
+ <!-- Custom GitHub SVG Icon -->
104
+ <svg class="sso-icon" viewBox="0 0 24 24" fill="currentColor">
105
+ <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"/>
106
+ </svg>
107
+ <span class="provider-label">GitHub</span>
108
+ <span class="toggle-state-text">Unlinked</span>
109
+ </div>
110
+ <div class="toggle-status-indicator bottom"></div>
111
+ </div>
84
112
  </div>
85
113
  <div id="sso-status-msg" class="status-msg hidden"></div>
86
114
  </div>
87
115
 
116
+ <!-- Change Passphrase Card -->
117
+ <div id="change-passphrase-card" class="card">
118
+ <h3>Change Master Passphrase</h3>
119
+ <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>
120
+ <div class="form-row">
121
+ <div class="form-group">
122
+ <label for="input-current-passphrase">Current Passphrase</label>
123
+ <input type="password" id="input-current-passphrase" placeholder="••••••••" class="form-input">
124
+ </div>
125
+ <div class="form-group">
126
+ <label for="input-new-passphrase">New Passphrase</label>
127
+ <input type="password" id="input-new-passphrase" placeholder="••••••••" class="form-input">
128
+ </div>
129
+ <div class="form-group">
130
+ <label for="input-confirm-passphrase">Confirm New Passphrase</label>
131
+ <input type="password" id="input-confirm-passphrase" placeholder="••••••••" class="form-input">
132
+ </div>
133
+ </div>
134
+ <div class="action-row">
135
+ <button id="btn-change-passphrase" class="action-btn">Update Passphrase</button>
136
+ </div>
137
+ <div id="change-passphrase-status" class="status-msg hidden"></div>
138
+ </div>
139
+
88
140
  <!-- Raw Keystone Timeline Explorer -->
89
141
  <div class="card accordion">
90
142
  <div id="raw-accordion-header" class="accordion-header">