@ibgib/space-gib 0.0.3 → 0.0.5

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 (63) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/IMPLEMENTATION.md +9 -13
  3. package/README.md +7 -0
  4. package/dist/client/bootstrap.mjs +1 -1
  5. package/dist/client/bootstrap.mjs.map +1 -1
  6. package/dist/client/chunk-ANGVYAEK.mjs +42 -0
  7. package/dist/client/chunk-ANGVYAEK.mjs.map +7 -0
  8. package/dist/client/chunk-IRGFDQRD.mjs +1920 -0
  9. package/dist/client/chunk-IRGFDQRD.mjs.map +7 -0
  10. package/dist/client/index.html +103 -5
  11. package/dist/client/index.mjs +1 -1
  12. package/dist/client/script.mjs +1 -1
  13. package/dist/client/style.css +466 -61
  14. package/dist/respec-gib.node.mjs +5 -0
  15. package/dist/server/server.mjs +533 -233
  16. package/dist/server/server.mjs.map +2 -2
  17. package/package.json +6 -6
  18. package/src/client/AUTO-GENERATED-version.mts +1 -1
  19. package/src/client/components/identity-header/IMPLEMENTATION.md +45 -0
  20. package/src/client/components/identity-header/identity-header.css +74 -0
  21. package/src/client/components/identity-header/identity-header.html +10 -0
  22. package/src/client/components/identity-header/identity-header.mts +361 -0
  23. package/src/client/components/identity-manager/IMPLEMENTATION.md +100 -0
  24. package/src/client/components/identity-manager/identity-manager.css +467 -0
  25. package/src/client/components/identity-manager/identity-manager.html +113 -0
  26. package/src/client/components/identity-manager/identity-manager.mts +767 -0
  27. package/src/client/components/keystone-creator/keystone-creator.css +2 -76
  28. package/src/client/components/keystone-creator/keystone-creator.html +41 -26
  29. package/src/client/components/keystone-creator/keystone-creator.mts +178 -41
  30. package/src/client/dev-tools/base-tools.mts +252 -0
  31. package/src/client/dev-tools/common.mts +217 -0
  32. package/src/client/dev-tools/phase-1.mts +156 -0
  33. package/src/client/dev-tools/phase-2.mts +143 -0
  34. package/src/client/dev-tools/phase-3.mts +189 -0
  35. package/src/client/dev-tools/phase-4-1.mts +197 -0
  36. package/src/client/dev-tools/phase-4-10.mts +884 -0
  37. package/src/client/dev-tools/phase-4-2.mts +388 -0
  38. package/src/client/dev-tools/phase-4-3.mts +391 -0
  39. package/src/client/dev-tools/phase-4-4.mts +374 -0
  40. package/src/client/dev-tools/phase-4-5.mts +376 -0
  41. package/src/client/dev-tools/phase-4-6.mts +273 -0
  42. package/src/client/dev-tools/phase-4-7.mts +399 -0
  43. package/src/client/dev-tools/phase-4-8.mts +430 -0
  44. package/src/client/dev-tools/phase-4-9.mts +398 -0
  45. package/src/client/dev-tools/phase-4.mts +1302 -0
  46. package/src/client/dev-tools.mts +52 -1194
  47. package/src/client/index.html +103 -5
  48. package/src/client/style.css +466 -61
  49. package/src/client/ui/shell/space-gib-shell-constants.mts +0 -2
  50. package/src/client/ui/shell/space-gib-shell-service.mts +82 -10
  51. package/src/common/common-constants.mts +0 -0
  52. package/src/common/keystone-policies.json +40 -43
  53. package/src/common/keystone-policies.mts +3 -5
  54. package/src/server/path-helper.respec.mts +99 -94
  55. package/src/server/serve-gib/README.md +9 -0
  56. package/src/server/serve-gib/handlers/api/keystone/keystone-genesis.handler.mts +1 -1
  57. package/src/server/serve-gib/handlers/api/keystone/keystone-get.respec.mts +1 -1
  58. package/src/server/serve-gib/handlers/ws/sync-upgrade-handler-base.mts +31 -3
  59. package/src/server/serve-gib/handlers/ws/ws-helper.mts +73 -45
  60. package/dist/client/chunk-2KJC5XKE.mjs +0 -31
  61. package/dist/client/chunk-2KJC5XKE.mjs.map +0 -7
  62. package/dist/client/chunk-QNIXTRFO.mjs +0 -235
  63. package/dist/client/chunk-QNIXTRFO.mjs.map +0 -7
@@ -0,0 +1,467 @@
1
+ :host {
2
+ display: block;
3
+ width: 100%;
4
+ max-width: 100%;
5
+ margin: 1rem auto;
6
+ font-family: var(--font-family-base, inherit);
7
+ font-size: var(--font-size-base, 1rem);
8
+ color: var(--text-color-base, var(--clr-text-primary, #ffffff));
9
+ box-sizing: border-box;
10
+ }
11
+
12
+ .component-container {
13
+ padding: 2rem;
14
+ background: var(--side-panel-tab-content-background-color, var(--clr-bg-glass, rgba(20, 20, 25, 0.6)));
15
+ backdrop-filter: blur(16px);
16
+ border-radius: var(--radius-lg, 12px);
17
+ border: var(--border-width-base, 1px) var(--border-style-base, solid) var(--border-color-base, var(--clr-border, rgba(255, 255, 255, 0.1)));
18
+ box-shadow: var(--shadow-card, 0 8px 32px 0 rgba(0, 0, 0, 0.37));
19
+ }
20
+
21
+ header {
22
+ display: flex;
23
+ flex-direction: column;
24
+ gap: 1rem;
25
+ margin-bottom: 2rem;
26
+ border-bottom: 1px solid var(--border-color-base, rgba(255, 255, 255, 0.1));
27
+ padding-bottom: 1rem;
28
+ }
29
+
30
+ h2 {
31
+ margin: 0;
32
+ font-size: var(--h2-font-size, 1.5rem);
33
+ font-weight: var(--h2-font-weight, 600);
34
+ color: var(--clr-accent, #50fa7b);
35
+ }
36
+
37
+
38
+ .icon-btn {
39
+ width: 2.2rem;
40
+ height: 2.2rem;
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ background: var(--button-background-color-base, rgba(255, 255, 255, 0.05));
45
+ border: 1px solid var(--button-border-color-base, rgba(255, 255, 255, 0.1));
46
+ border-radius: var(--button-border-radius-base, 50%);
47
+ color: var(--button-text-color-base, #ffffff);
48
+ font-size: 1.2rem;
49
+ cursor: pointer;
50
+ transition: all 0.2s ease-in-out;
51
+ }
52
+
53
+ .icon-btn:hover {
54
+ background: var(--button-hover-background-color, var(--clr-accent, #50fa7b));
55
+ color: var(--button-hover-text-color, #1a1a24);
56
+ border-color: var(--button-hover-border-color, var(--clr-accent, #50fa7b));
57
+ }
58
+
59
+ .content {
60
+ display: flex;
61
+ flex-direction: column;
62
+ gap: 1.5rem;
63
+ }
64
+
65
+ .placeholder-view {
66
+ padding: 3rem 1rem;
67
+ text-align: center;
68
+ background: rgba(0, 0, 0, 0.15);
69
+ border-radius: var(--radius-md, 8px);
70
+ border: 1px dashed var(--border-color-base, rgba(255, 255, 255, 0.1));
71
+ }
72
+
73
+ .placeholder-view p {
74
+ color: var(--clr-text-secondary, #b3b3b3);
75
+ margin-bottom: 1.5rem;
76
+ }
77
+
78
+ .card {
79
+ padding: 1.5rem;
80
+ background: rgba(255, 255, 255, 0.02);
81
+ border: 1px solid var(--border-color-base, rgba(255, 255, 255, 0.05));
82
+ border-radius: var(--radius-md, 8px);
83
+ display: flex;
84
+ flex-direction: column;
85
+ gap: 1rem;
86
+ }
87
+
88
+ .card h3 {
89
+ margin: 0;
90
+ font-size: var(--h3-font-size, 1.15rem);
91
+ font-weight: var(--h3-font-weight, 500);
92
+ color: var(--clr-accent, #50fa7b);
93
+ }
94
+
95
+ .info-group {
96
+ display: flex;
97
+ flex-direction: column;
98
+ gap: 0.5rem;
99
+ }
100
+
101
+ .info-group label {
102
+ font-size: 0.8rem;
103
+ color: var(--clr-text-secondary, #b3b3b3);
104
+ text-transform: uppercase;
105
+ letter-spacing: 0.05em;
106
+ }
107
+
108
+
109
+ .replicas-list {
110
+ display: flex;
111
+ flex-direction: column;
112
+ gap: 0.5rem;
113
+ max-height: 150px;
114
+ overflow-y: auto;
115
+ }
116
+
117
+ .input-row {
118
+ display: flex;
119
+ gap: 0.5rem;
120
+ }
121
+
122
+ /* Accordion raw styles */
123
+ .accordion {
124
+ padding: 0;
125
+ overflow: hidden;
126
+ }
127
+
128
+ .accordion-header {
129
+ padding: 1.25rem 1.5rem;
130
+ display: flex;
131
+ justify-content: space-between;
132
+ align-items: center;
133
+ cursor: pointer;
134
+ background: rgba(255, 255, 255, 0.01);
135
+ transition: background 0.2s ease-in-out;
136
+ }
137
+
138
+ .accordion-header:hover {
139
+ background: rgba(255, 255, 255, 0.03);
140
+ }
141
+
142
+ .accordion-header .chevron {
143
+ transition: transform 0.2s ease-in-out;
144
+ font-size: 0.8rem;
145
+ color: var(--clr-text-secondary, #b3b3b3);
146
+ }
147
+
148
+ .accordion-header.expanded .chevron {
149
+ transform: rotate(180deg);
150
+ }
151
+
152
+ .accordion-content {
153
+ max-height: 0;
154
+ transition: max-height 0.3s cubic-bezier(0, 1, 0, 1);
155
+ background: rgba(0, 0, 0, 0.15);
156
+ border-top: 1px solid var(--border-color-base, rgba(255, 255, 255, 0.03));
157
+ }
158
+
159
+ .accordion-content.expanded {
160
+ max-height: 5000px;
161
+ overflow-y: visible;
162
+ transition: max-height 0.3s cubic-bezier(1, 0, 1, 0);
163
+ }
164
+
165
+ .json-code {
166
+ margin: 0;
167
+ padding: 1.25rem;
168
+ font-family: var(--font-mono, monospace);
169
+ font-size: 0.8rem;
170
+ color: var(--clr-accent, #50fa7b);
171
+ background: transparent;
172
+ overflow: auto;
173
+ max-height: 70dvh;
174
+ white-space: pre-wrap;
175
+ word-break: break-all;
176
+ }
177
+
178
+ .description {
179
+ font-size: 0.85rem;
180
+ color: var(--clr-text-secondary, #b3b3b3);
181
+ margin: 0;
182
+ }
183
+
184
+
185
+ .hidden {
186
+ display: none !important;
187
+ }
188
+
189
+ .info-group-grid {
190
+ display: grid;
191
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
192
+ gap: 1rem;
193
+ margin-top: 0.5rem;
194
+ }
195
+
196
+ .value-text {
197
+ font-family: var(--font-family-base, inherit);
198
+ font-size: 0.9rem;
199
+ color: var(--text-color-base, #ffffff);
200
+ font-weight: 500;
201
+ }
202
+
203
+ .pools-container {
204
+ display: flex;
205
+ flex-direction: column;
206
+ gap: 1rem;
207
+ }
208
+
209
+ .pool-card {
210
+ padding: 1rem;
211
+ background: rgba(0, 0, 0, 0.25);
212
+ border: 1px solid var(--border-color-base, rgba(255, 255, 255, 0.05));
213
+ border-radius: 6px;
214
+ display: flex;
215
+ flex-direction: column;
216
+ gap: 0.75rem;
217
+ }
218
+
219
+ .pool-header {
220
+ display: flex;
221
+ justify-content: space-between;
222
+ align-items: center;
223
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
224
+ padding-bottom: 0.5rem;
225
+ }
226
+
227
+ .pool-title {
228
+ font-size: 0.95rem;
229
+ font-weight: 600;
230
+ color: var(--clr-accent, #50fa7b);
231
+ }
232
+
233
+ .pool-tag {
234
+ font-size: 0.7rem;
235
+ padding: 0.15rem 0.4rem;
236
+ border-radius: 4px;
237
+ font-weight: bold;
238
+ text-transform: uppercase;
239
+ }
240
+
241
+ .pool-tag.foreign {
242
+ background: rgba(255, 184, 108, 0.15);
243
+ border: 1px solid rgba(255, 184, 108, 0.3);
244
+ color: #ffb86c;
245
+ }
246
+
247
+ .pool-tag.native {
248
+ background: rgba(80, 250, 123, 0.1);
249
+ border: 1px solid rgba(80, 250, 123, 0.2);
250
+ color: #50fa7b;
251
+ }
252
+
253
+ .pool-grid {
254
+ display: grid;
255
+ grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
256
+ gap: 0.75rem;
257
+ font-size: 0.85rem;
258
+ }
259
+
260
+ .pool-field {
261
+ display: flex;
262
+ flex-direction: column;
263
+ gap: 0.2rem;
264
+ }
265
+
266
+ .pool-field label {
267
+ font-size: 0.7rem;
268
+ color: var(--clr-text-secondary, #b3b3b3);
269
+ text-transform: uppercase;
270
+ letter-spacing: 0.03em;
271
+ }
272
+
273
+ .pool-field span {
274
+ color: #ffffff;
275
+ font-weight: 500;
276
+ word-break: break-all;
277
+ }
278
+
279
+ /* Key-Value Details Grid Layout */
280
+ .kv-grid {
281
+ display: grid;
282
+ grid-template-columns: minmax(140px, 180px) 1fr;
283
+ gap: 0.75rem 1.5rem;
284
+ align-items: baseline;
285
+ margin-top: 1rem;
286
+ margin-bottom: 1.5rem;
287
+ }
288
+
289
+ .kv-label {
290
+ font-family: var(--font-sans);
291
+ font-size: 0.75rem;
292
+ font-weight: 600;
293
+ text-transform: uppercase;
294
+ letter-spacing: 0.05em;
295
+ color: var(--clr-text-secondary, #8fa08f);
296
+ user-select: none;
297
+ }
298
+
299
+ .kv-value {
300
+ font-size: 0.9375rem;
301
+ color: var(--clr-text-primary, #ffffff);
302
+ word-break: break-all;
303
+ }
304
+
305
+ .kv-pre {
306
+ margin: 0;
307
+ padding: 0.6rem 0.8rem;
308
+ background: rgba(0, 0, 0, 0.3);
309
+ border: 1px solid var(--border-color-base, rgba(255, 255, 255, 0.05));
310
+ border-radius: var(--radius-sm, 6px);
311
+ font-family: var(--font-mono, monospace);
312
+ font-size: 0.8rem;
313
+ color: var(--clr-accent, #50fa7b);
314
+ max-height: 150px;
315
+ overflow: auto;
316
+ white-space: pre;
317
+ word-break: normal;
318
+ }
319
+
320
+ /* Timeline Scrubber Navigation */
321
+ .scrubber-nav {
322
+ display: flex;
323
+ align-items: center;
324
+ justify-content: center;
325
+ gap: 0.5rem;
326
+ padding: 0.75rem;
327
+ background: rgba(0, 0, 0, 0.2);
328
+ border: 1px solid var(--border-color-base, rgba(255, 255, 255, 0.05));
329
+ border-radius: var(--radius-md, 8px);
330
+ margin-top: 1rem;
331
+ margin-bottom: 1.5rem;
332
+ }
333
+
334
+ .scrubber-info {
335
+ font-family: var(--font-mono, monospace);
336
+ font-size: 0.85rem;
337
+ color: var(--clr-accent, #50fa7b);
338
+ min-width: 120px;
339
+ text-align: center;
340
+ font-weight: 500;
341
+ }
342
+
343
+ .scrubber-btn {
344
+ padding: 0.4rem 0.8rem;
345
+ font-size: 0.8rem;
346
+ min-width: 2.2rem;
347
+ }
348
+
349
+ /* Pool Details & Challenges/Binding Map styling */
350
+ .pool-details {
351
+ margin-top: 0.75rem;
352
+ border-top: 1px solid rgba(255, 255, 255, 0.05);
353
+ padding-top: 0.5rem;
354
+ }
355
+
356
+ .pool-details-summary {
357
+ font-size: 0.8rem;
358
+ font-weight: 600;
359
+ color: var(--clr-text-secondary, #8fa08f);
360
+ cursor: pointer;
361
+ user-select: none;
362
+ outline: none;
363
+ padding: 0.25rem 0;
364
+ display: flex;
365
+ align-items: center;
366
+ gap: 0.25rem;
367
+ transition: color var(--t-fast, 120ms ease);
368
+ }
369
+
370
+ .pool-details-summary:hover {
371
+ color: var(--clr-accent, #78f87e);
372
+ }
373
+
374
+ .pool-challenges-list {
375
+ margin-top: 0.5rem;
376
+ display: flex;
377
+ flex-direction: column;
378
+ gap: 0.4rem;
379
+ max-height: 180px;
380
+ overflow-y: auto;
381
+ padding-right: 0.25rem;
382
+ border: 1px solid rgba(255, 255, 255, 0.05);
383
+ background: rgba(0, 0, 0, 0.15);
384
+ border-radius: 4px;
385
+ padding: 0.5rem;
386
+ }
387
+
388
+ .pool-challenge-item {
389
+ display: flex;
390
+ justify-content: space-between;
391
+ align-items: center;
392
+ background: rgba(255, 255, 255, 0.02);
393
+ border: 1px solid rgba(255, 255, 255, 0.03);
394
+ border-radius: 4px;
395
+ padding: 0.35rem 0.5rem;
396
+ font-size: 0.75rem;
397
+ font-family: var(--font-mono, monospace);
398
+ }
399
+
400
+ .challenge-id {
401
+ color: var(--clr-text-secondary, #8fa08f);
402
+ font-weight: 500;
403
+ }
404
+
405
+ .challenge-hash {
406
+ color: var(--clr-accent, #78f87e);
407
+ word-break: break-all;
408
+ margin-left: 1rem;
409
+ text-align: right;
410
+ }
411
+
412
+ .pool-binding-map {
413
+ margin-top: 0.5rem;
414
+ display: grid;
415
+ grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
416
+ gap: 0.4rem;
417
+ max-height: 200px;
418
+ overflow-y: auto;
419
+ padding-right: 0.25rem;
420
+ border: 1px solid rgba(255, 255, 255, 0.05);
421
+ background: rgba(0, 0, 0, 0.15);
422
+ border-radius: 4px;
423
+ padding: 0.5rem;
424
+ }
425
+
426
+ .binding-bucket {
427
+ display: flex;
428
+ flex-direction: column;
429
+ align-items: center;
430
+ background: rgba(255, 255, 255, 0.02);
431
+ border: 1px solid rgba(255, 255, 255, 0.03);
432
+ border-radius: 4px;
433
+ padding: 0.35rem;
434
+ font-family: var(--font-mono, monospace);
435
+ font-size: 0.75rem;
436
+ }
437
+
438
+ .binding-key {
439
+ color: var(--clr-text-secondary, #8fa08f);
440
+ font-weight: bold;
441
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
442
+ width: 100%;
443
+ text-align: center;
444
+ padding-bottom: 0.15rem;
445
+ margin-bottom: 0.15rem;
446
+ }
447
+
448
+ .binding-ids {
449
+ display: flex;
450
+ flex-direction: column;
451
+ gap: 0.15rem;
452
+ width: 100%;
453
+ align-items: center;
454
+ }
455
+
456
+ .binding-id-tag {
457
+ font-size: 0.65rem;
458
+ background: rgba(120, 248, 126, 0.08);
459
+ color: var(--clr-accent, #78f87e);
460
+ padding: 0.05rem 0.25rem;
461
+ border-radius: 3px;
462
+ width: 100%;
463
+ text-align: center;
464
+ white-space: nowrap;
465
+ overflow: hidden;
466
+ text-overflow: ellipsis;
467
+ }
@@ -0,0 +1,113 @@
1
+ <div id="container" class="component-container">
2
+ <header id="identity-manager-header">
3
+ <h2 id="title">Identity Manager</h2>
4
+ <div class="tabs-row">
5
+ <div id="identity-tabs" class="tabs-list">
6
+ <!-- Tabs will be dynamically injected here -->
7
+ </div>
8
+ <button id="btn-add-identity" class="icon-btn" title="Create or Load Identity">+</button>
9
+ </div>
10
+ </header>
11
+
12
+ <div id="identity-manager-content" class="content">
13
+ <!-- Active child or keystone-creator gets injected here -->
14
+ <div id="no-identity-placeholder" class="placeholder-view">
15
+ <p>No Domain Identities loaded. Create or load one to begin.</p>
16
+ <button id="btn-create-placeholder" class="action-btn">Create/Load Identity</button>
17
+ </div>
18
+
19
+ <div id="identity-details-view" class="details-view hidden">
20
+ <!-- Details for the active Domain Identity -->
21
+ <div class="card">
22
+ <h3>Domain Identity Details</h3>
23
+
24
+ <!-- History Scrubber Navigation -->
25
+ <div id="history-scrubber" class="scrubber-nav">
26
+ <button id="btn-scrub-first" class="action-btn secondary scrubber-btn"
27
+ title="First Frame (Genesis)">|&lt;</button>
28
+ <button id="btn-scrub-prev10" class="action-btn secondary scrubber-btn"
29
+ title="Back 10 Frames">&lt;&lt; 10</button>
30
+ <button id="btn-scrub-prev" class="action-btn secondary scrubber-btn"
31
+ title="Previous Frame">&lt;</button>
32
+ <span id="scrubber-status" class="scrubber-info">Frame - / -</span>
33
+ <button id="btn-scrub-next" class="action-btn secondary scrubber-btn"
34
+ title="Next Frame">&gt;</button>
35
+ <button id="btn-scrub-next10" class="action-btn secondary scrubber-btn" title="Forward 10 Frames">10
36
+ &gt;&gt;</button>
37
+ <button id="btn-scrub-latest" class="action-btn secondary scrubber-btn"
38
+ title="Latest Frame (Tip)">&gt;|</button>
39
+ </div>
40
+
41
+ <!-- Key-Value Grid -->
42
+ <div class="kv-grid">
43
+ <div class="kv-label">Username</div>
44
+ <div id="identity-name" class="kv-value">-</div>
45
+
46
+ <div class="kv-label">Description</div>
47
+ <div id="identity-description" class="kv-value">-</div>
48
+
49
+ <div class="kv-label">Verifiable Address</div>
50
+ <code id="identity-addr" class="address-code"></code>
51
+
52
+ <div class="kv-label">Generation (n)</div>
53
+ <div id="identity-gen" class="kv-value">-</div>
54
+
55
+ <div class="kv-label">Timestamp</div>
56
+ <div id="identity-timestamp" class="kv-value">-</div>
57
+
58
+ <div class="kv-label">UUID</div>
59
+ <div id="identity-uuid" class="kv-value">-</div>
60
+
61
+ <div class="kv-label">Frame Details</div>
62
+ <div class="kv-value">
63
+ <pre id="identity-frame-details" class="kv-pre">-</pre>
64
+ </div>
65
+
66
+ <div class="kv-label">Aggr. Details</div>
67
+ <div class="kv-value">
68
+ <pre id="identity-aggr-details" class="kv-pre">-</pre>
69
+ </div>
70
+ </div>
71
+
72
+ <div class="action-row">
73
+ <button id="btn-set-active" class="action-btn">Set as Active Identity</button>
74
+ <button id="btn-verify-chain" class="action-btn secondary">Verify Identity Chain</button>
75
+ <!-- <button id="btn-sync-identity" class="action-btn" disabled>Sync Identity & Data</button> -->
76
+ </div>
77
+ <div id="verification-status" class="status-msg hidden"></div>
78
+ </div>
79
+
80
+ <!-- Challenge Pools Card -->
81
+ <div class="card">
82
+ <h3>Challenge Pools</h3>
83
+ <div id="pools-container" class="pools-container">
84
+ <!-- Dynamic pools list gets injected here -->
85
+ </div>
86
+ </div>
87
+
88
+ <!-- Replicas / Sync Peers Repository Manager -->
89
+ <!-- <div class="card">
90
+ <h3>Replication & Spaces</h3>
91
+ <p class="description">Manage remote space providers where this identity's data is replicated.</p>
92
+ <div id="replicas-list" class="replicas-list"> -->
93
+ <!-- Configured space URLs listed here -->
94
+ <!-- </div>
95
+ <div class="input-row">
96
+ <input type="url" id="input-replica-url" placeholder="https://space.example.com/api" class="text-input" disabled>
97
+ <button id="btn-add-replica" class="action-btn secondary" disabled>Add Space</button>
98
+ </div>
99
+ </div> -->
100
+
101
+ <!-- Raw Keystone Timeline Explorer -->
102
+ <div class="card accordion">
103
+ <div id="raw-accordion-header" class="accordion-header">
104
+ <span>Raw Keystone Timeline (JSON)</span>
105
+ <span class="chevron">▼</span>
106
+ </div>
107
+ <div id="raw-accordion-content" class="accordion-content">
108
+ <pre id="raw-keystone-json" class="json-code"></pre>
109
+ </div>
110
+ </div>
111
+ </div>
112
+ </div>
113
+ </div>