@ibgib/space-gib 0.0.9 → 0.0.13

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 (82) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -0
  3. package/dist/client/bootstrap.mjs +33 -33
  4. package/dist/client/bootstrap.mjs.map +3 -3
  5. package/dist/client/chunk-ROJZUPPE.mjs +19 -0
  6. package/dist/client/chunk-ROJZUPPE.mjs.map +7 -0
  7. package/dist/client/chunk-WJHRARK6.mjs +2329 -0
  8. package/dist/client/chunk-WJHRARK6.mjs.map +7 -0
  9. package/dist/client/index.mjs +22 -1
  10. package/dist/client/index.mjs.map +4 -4
  11. package/dist/client/script.mjs +1 -1
  12. package/dist/server/server.mjs +19147 -18210
  13. package/dist/server/server.mjs.map +4 -4
  14. package/package.json +4 -4
  15. package/space-gib.localhost-1785337158142.log +75 -0
  16. package/src/client/AUTO-GENERATED-version.mts +1 -1
  17. package/src/client/README.md +1 -1
  18. package/src/client/api/space-gib-api-bridge.mts +8 -224
  19. package/src/client/ui/shell/space-gib-shell-service.mts +68 -18
  20. package/src/common/keystone-policies.mts +1 -1
  21. package/src/server/README.md +3 -2
  22. package/src/server/server.mts +13 -32
  23. package/src/server/test.json +0 -0
  24. package/dist/client/chunk-ACIGPCQW.mjs +0 -2407
  25. package/dist/client/chunk-ACIGPCQW.mjs.map +0 -7
  26. package/dist/client/chunk-QRMTJE6M.mjs +0 -42
  27. package/dist/client/chunk-QRMTJE6M.mjs.map +0 -7
  28. package/space-gib.localhost-1783713259760.log +0 -45
  29. package/src/client/components/identity-header/IMPLEMENTATION.md +0 -45
  30. package/src/client/components/identity-header/identity-header.css +0 -112
  31. package/src/client/components/identity-header/identity-header.html +0 -11
  32. package/src/client/components/identity-header/identity-header.mts +0 -439
  33. package/src/client/components/identity-manager/IMPLEMENTATION.md +0 -100
  34. package/src/client/components/identity-manager/identity-manager.css +0 -171
  35. package/src/client/components/identity-manager/identity-manager.html +0 -19
  36. package/src/client/components/identity-manager/identity-manager.mts +0 -639
  37. package/src/client/components/keystone-creator/keystone-creator.css +0 -65
  38. package/src/client/components/keystone-creator/keystone-creator.html +0 -41
  39. package/src/client/components/keystone-creator/keystone-creator.mts +0 -443
  40. package/src/client/components/keystone-details/keystone-details.css +0 -611
  41. package/src/client/components/keystone-details/keystone-details.html +0 -151
  42. package/src/client/components/keystone-details/keystone-details.mts +0 -1213
  43. package/src/client/components/keystone-scrubber/SCRUBBER_IMPLEMENTATION.md +0 -33
  44. package/src/client/components/keystone-scrubber/keystone-scrubber.css +0 -46
  45. package/src/client/components/keystone-scrubber/keystone-scrubber.html +0 -15
  46. package/src/client/components/keystone-scrubber/keystone-scrubber.mts +0 -356
  47. package/src/server/bootstrap-helper.mts +0 -141
  48. package/src/server/bootstrap-helper.respec.mts +0 -100
  49. package/src/server/metaspace-nodeindexedspace/metaspace-nodeindexedspace.mts +0 -85
  50. package/src/server/path-constants.mts +0 -101
  51. package/src/server/path-helper.mts +0 -101
  52. package/src/server/path-helper.respec.mts +0 -99
  53. package/src/server/serve-gib/CHANGELOG.md +0 -29
  54. package/src/server/serve-gib/README.md +0 -43
  55. package/src/server/serve-gib/constants.mts +0 -1
  56. package/src/server/serve-gib/handlers/api/debug/ws-echo.handler.mts +0 -105
  57. package/src/server/serve-gib/handlers/api/health.handler.mts +0 -23
  58. package/src/server/serve-gib/handlers/api/health.respec.mts +0 -51
  59. package/src/server/serve-gib/handlers/api/ibgib/ibgib-handler-types.mts +0 -49
  60. package/src/server/serve-gib/handlers/api/ibgib/ibgib.handler.mts +0 -176
  61. package/src/server/serve-gib/handlers/api/keystone/keystone-evolve.handler.mts +0 -150
  62. package/src/server/serve-gib/handlers/api/keystone/keystone-genesis.handler.mts +0 -146
  63. package/src/server/serve-gib/handlers/api/keystone/keystone-get.handler.mts +0 -198
  64. package/src/server/serve-gib/handlers/api/keystone/keystone-get.respec.mts +0 -107
  65. package/src/server/serve-gib/handlers/api/keystone/keystone-handler-types.mts +0 -29
  66. package/src/server/serve-gib/handlers/api/keystone/keystone-post.handler.mts +0 -55
  67. package/src/server/serve-gib/handlers/api/keystone/keystone-post.respec.mts +0 -130
  68. package/src/server/serve-gib/handlers/api/keystone/sso-config.handler.mts +0 -66
  69. package/src/server/serve-gib/handlers/api/keystone/sso-link.handler.mts +0 -140
  70. package/src/server/serve-gib/handlers/api/keystone/sso-login.handler.mts +0 -190
  71. package/src/server/serve-gib/handlers/error-handler.mts +0 -36
  72. package/src/server/serve-gib/handlers/handler-base.mts +0 -383
  73. package/src/server/serve-gib/handlers/static-handler.mts +0 -82
  74. package/src/server/serve-gib/handlers/ws/sync-upgrade-handler-base.mts +0 -233
  75. package/src/server/serve-gib/handlers/ws/sync-upgrade.handler.mts +0 -24
  76. package/src/server/serve-gib/handlers/ws/ws-helper.mts +0 -216
  77. package/src/server/serve-gib/handlers/ws/ws-types.mts +0 -53
  78. package/src/server/serve-gib/serve-gib-helpers.mts +0 -32
  79. package/src/server/serve-gib/serve-gib-v1.mts +0 -172
  80. package/src/server/serve-gib/serve-gib.respec.mts +0 -90
  81. package/src/server/serve-gib/types.mts +0 -102
  82. package/src/server/server-constants.mts +0 -2
@@ -1,45 +0,0 @@
1
- script.mjs:7 space-gib early script executing...
2
- chunk-OVS3VYAL.mjs:27047 [getSpaceGibShellSvc] initializing SpaceGibShellService singleton on globalThis... (I: genuuid)
3
- chunk-OVS3VYAL.mjs:108 [initialize] does nothing atow (I: 65bb46c88c82b637ad928b8bf1a07225)
4
- index.mjs:24 [spinOffStartup]: 0.134033203125 ms DOMContentLoaded fired
5
- index.mjs:26 [spinOffStartup]: 57.553955078125 ms initIbGibStorage complete
6
- bootstrap.mjs:9643 [space-gib bootstrap] version: 0.0.6
7
- bootstrap.mjs:7586 [bootstrapIbGibApp] starting...
8
- bootstrap.mjs:366 [buildArgInfos] starting... (I: f389aaa490796dfd823bc7b9d4e58b23)
9
- bootstrap.mjs:376 identifier: interactive (I: 519ce129a1e34753a9070d3a205c9a8b)
10
- bootstrap.mjs:462 [buildArgInfos] complete.
11
- bootstrap.mjs:7639 [execFromArgs] starting...
12
- bootstrap.mjs:7681 [initMetaspace] starting...
13
- chunk-D2MM5RDN.mjs:72 [Violation] 'setTimeout' handler took 70ms
14
- bootstrap.mjs:2495 [Metaspace_Webspace][initialize] initialized (I: e3b3a9652c09445cb055013166ff089c)
15
- bootstrap.mjs:7708 [initMetaspace] complete.
16
- chunk-OVS3VYAL.mjs:20874 [registerFunctionInfos] starting... (I: 14fee8e27384a040494542182031ae25)
17
- chunk-OVS3VYAL.mjs:20893 [registerFunctionInfos] complete.
18
- bootstrap.mjs:7725 [execInteractive] starting...
19
- bootstrap.mjs:7758 [defaultGetOrCreateApp] starting...
20
- bootstrap.mjs:7826 [defaultGetOrCreateApp] complete.
21
- bootstrap.mjs:8503 [SpaceGibApp_V1] space-gib initialized and ready.
22
- bootstrap.mjs:7748 [execInteractive] complete.
23
- bootstrap.mjs:7671
24
- [execFromArgs] complete.
25
- chunk-OVS3VYAL.mjs:27020 [SpaceGibShellService][onEngineReady] SpaceGib Shell Service is ready.
26
- bootstrap.mjs:7629
27
- [bootstrapIbGibApp] complete.
28
- index.mjs:28 [spinOffStartup]: 920.193115234375 ms dynamicallyLoadBootstrapScript complete
29
- index.mjs:30 [spinOffStartup]: 924.22314453125 ms initDevTools complete
30
- index.mjs:31 [spinOffStartup]: 924.443115234375 ms
31
- chunk-OVS3VYAL.mjs:26572 yes this is being updated! I am just wondering if I am seeing old code in the browser, i.e., if refresh is happening or just getting cache (I: 6599db11c1086062b8f5e86db89cba26)
32
- chunk-OVS3VYAL.mjs:26575 KeystoneScrubberComponentInstance[ctor] (I: 3adca837d5c898d8e839d23c59538126)
33
- chunk-OVS3VYAL.mjs:26583 [KeystoneScrubberComponentInstance][initialize] starting... (I: 75eecfc01af7f3fa9897932ec5457526)
34
- chunk-OVS3VYAL.mjs:26638 [KeystoneScrubberComponentInstance][loadIbGib] starting... (I: a4a9181bbb58a22cc71c8745a91ec426)
35
- chunk-OVS3VYAL.mjs:26648 [KeystoneScrubberComponentInstance][loadIbGib] complete.
36
- chunk-OVS3VYAL.mjs:26592 [KeystoneScrubberComponentInstance][initialize] complete.
37
- chunk-OVS3VYAL.mjs:26600 [KeystoneScrubberComponentInstance][created] starting... (I: bc16e6212928658ed8034c75b6279526)
38
- chunk-OVS3VYAL.mjs:26572 yes this is being updated! I am just wondering if I am seeing old code in the browser, i.e., if refresh is happening or just getting cache (I: 6599db11c1086062b8f5e86db89cba26)
39
- chunk-OVS3VYAL.mjs:26575 KeystoneScrubberComponentInstance[ctor] (I: 3adca837d5c898d8e839d23c59538126)
40
- chunk-OVS3VYAL.mjs:26583 [KeystoneScrubberComponentInstance][initialize] starting... (I: 75eecfc01af7f3fa9897932ec5457526)
41
- chunk-OVS3VYAL.mjs:26638 [KeystoneScrubberComponentInstance][loadIbGib] starting... (I: a4a9181bbb58a22cc71c8745a91ec426)
42
- chunk-OVS3VYAL.mjs:26648 [KeystoneScrubberComponentInstance][loadIbGib] complete.
43
- chunk-OVS3VYAL.mjs:26592 [KeystoneScrubberComponentInstance][initialize] complete.
44
- chunk-OVS3VYAL.mjs:26600 [KeystoneScrubberComponentInstance][created] starting... (I: bc16e6212928658ed8034c75b6279526)
45
- chunk-OVS3VYAL.mjs:24584 [IdentityManagerComponentInstance][activateIbGib] same tab already active. returning early. childInfo.addr: keystone^442D637B4066E3D0A73A467C14F71FE9FDAA5C5A7FC7EA28064877A63A914C44.5D0EC2067890F88736364BBE9BD59C80DCB99FC85132B3637072D274077D8CA6 (user just clicked on the same tab) (I: e67c0d02f3143c49c7a20c82d0730225)
@@ -1,45 +0,0 @@
1
- # Identity Header Component - Implementation Spec
2
-
3
- This document details the layout, styling, and behavior for the `identity-header` component (`ibgib-identity-header`). It is rendered inside the app shell's header and acts as a status indicator and shortcut route for the user's active identity.
4
-
5
- ## Requirements
6
-
7
- 1. **State-Driven Display**:
8
- - **Active Identity Mode**: If an active Domain Identity (Keystone) address exists in settings and is resolved in the local space, the component displays an identity pill showing a truncated version of the address.
9
- - **Inactive/Default Mode**: If no identity is resolved, the component renders a prominent "Create Identity" button.
10
- 2. **Interactive Routing**:
11
- - Clicking either the identity pill or the fallback "Create Identity" button calls `SpaceGibShellService.showIdentityManager()` to load the full `<ibgib-identity-manager>` component in the center view panel.
12
- 3. **Agent-Themeable Styles**:
13
- - The layout must be highly compact to fit inside a standard horizontal header panel.
14
- - All styling must prioritize valid theme CSS variables (e.g., `--button-background-color-base`, `--tab-text-color-active`) to remain dynamic and styleable by runtime agents.
15
- 4. **Shared Settings Scope**:
16
- - It is initialized with the virtual `ROOT_ADDR` and manually binds to the `"keystones"` index `ibgib`.
17
- - It initializes its coupled settings via `this.initSettings()`. Since both this component and the manager share the `"keystones"` index backing model, they automatically resolve the exact same coupled settings `ibgib` and settings timeline, reactively syncing active identity selection changes.
18
- - For detailed data schema, see [identity-manager IMPLEMENTATION.md](../identity-manager/IMPLEMENTATION.md).
19
-
20
- ---
21
-
22
- ## Component Structure
23
-
24
- * **[identity-header.mts](file:///c:/Users/billm/antigravity/ibgib/apps/space-gib/src/client/components/identity-header/identity-header.mts)**: Element definition, lifecycle events, active identity resolution, shell service navigation call.
25
- * **[identity-header.html](file:///c:/Users/billm/antigravity/ibgib/apps/space-gib/src/client/components/identity-header/identity-header.html)**: Compact HTML structures for the pill and fallback button.
26
- * **[identity-header.css](file:///c:/Users/billm/antigravity/ibgib/apps/space-gib/src/client/components/identity-header/identity-header.css)**: Glassmorphic pill styling matching current themes.
27
-
28
- ---
29
-
30
- ## Implementation Checklist
31
-
32
- ### Phase 1: Basic Scaffolding & Setup
33
- - [x] Scaffold `identity-header.mts`, `.html`, and `.css` files.
34
- - [x] Register `IdentityHeaderComponentMeta` with `IbGibComponentService`.
35
- - [x] Mount `<ibgib-identity-header>` inside the header panel in `SpaceGibShellService`.
36
-
37
- ### Phase 2: Navigation & Identity State
38
- - [x] Wire up click handlers to trigger center-panel navigation to `ibgib-identity-manager`.
39
- - [x] Resolve settings and check the `"keystones"` index to render the appropriate active/inactive view mode.
40
-
41
- ### Phase 3: Visual Polish & Bugs
42
- - [ ] Ensure the header component has an initial size/button and is visible while the page is initializing.
43
-
44
- ### Testing Note
45
- - [ ] **Manual Testing Only**: Visual integration and navigation behavior will be verified manually by the developer to limit token consumption.
@@ -1,112 +0,0 @@
1
- :host {
2
- display: inline-block;
3
- vertical-align: middle;
4
- }
5
-
6
- .header-widget-container {
7
- display: flex;
8
- align-items: center;
9
- justify-content: flex-end;
10
- }
11
-
12
- /* Glassmorphic identity status pill */
13
- .identity-pill {
14
- display: flex;
15
- align-items: center;
16
- gap: 0.5rem;
17
- padding: 0.4rem 0.8rem;
18
- background: var(--tab-background-color-active, rgba(255, 255, 255, 0.1));
19
- border: 1px solid var(--tab-border-color-active, rgba(80, 250, 123, 0.3));
20
- border-radius: var(--radius-lg, 20px);
21
- cursor: default;
22
- transition: all 0.2s ease-in-out;
23
- }
24
-
25
- .identity-pill:hover {
26
- background: rgba(80, 250, 123, 0.15);
27
- border-color: var(--clr-accent, #50fa7b);
28
- box-shadow: 0 2px 8px rgba(80, 250, 123, 0.1);
29
- }
30
-
31
- .avatar-circle {
32
- display: flex;
33
- align-items: center;
34
- justify-content: center;
35
- width: 24px;
36
- height: 24px;
37
- border-radius: 50%;
38
- font-size: 0.85rem;
39
- font-weight: 700;
40
- text-transform: uppercase;
41
- background: var(--clr-accent, #50fa7b);
42
- color: #11111b;
43
- flex-shrink: 0;
44
- }
45
-
46
- .address-text {
47
- font-family: var(--font-sans, sans-serif);
48
- font-size: 0.85rem;
49
- color: var(--clr-text-primary, #ffffff);
50
- font-weight: 500;
51
- }
52
-
53
- /* Fallback button when no identity is loaded */
54
- .action-btn {
55
- padding: 0.4rem 0.9rem;
56
- border-radius: 20px;
57
- font-size: 0.8rem;
58
- background: transparent;
59
- border: 1px dashed var(--clr-warn, #ffcc44);
60
- color: var(--clr-warn, #ffcc44);
61
- cursor: pointer;
62
- transition: all 0.2s ease-in-out;
63
- }
64
-
65
- .action-btn:hover {
66
- background: rgba(255, 204, 68, 0.1);
67
- border-color: var(--clr-warn, #ffcc44);
68
- box-shadow: 0 0 8px rgba(255, 204, 68, 0.2);
69
- }
70
-
71
- .hidden {
72
- display: none !important;
73
- }
74
-
75
- /* Styled selector dropdown */
76
- .identity-select {
77
- font-family: var(--font-sans, sans-serif);
78
- font-size: 0.85rem;
79
- color: var(--clr-text-primary, #ffffff);
80
- background: transparent;
81
- border: none;
82
- cursor: pointer;
83
- font-weight: 500;
84
- outline: none;
85
- padding: 0 0.2rem;
86
- max-width: 150px;
87
- text-overflow: ellipsis;
88
- }
89
-
90
- .identity-select option {
91
- background: var(--clr-bg-surface, #1e1e2e);
92
- color: var(--clr-text-primary, #ffffff);
93
- }
94
-
95
- /* Gear manage button */
96
- .manage-btn {
97
- background: transparent;
98
- border: none;
99
- font-size: 1rem;
100
- cursor: pointer;
101
- padding: 0 0.2rem;
102
- display: flex;
103
- align-items: center;
104
- justify-content: center;
105
- color: var(--clr-text-secondary, #b3b3b3);
106
- transition: color 0.2s ease, transform 0.2s ease;
107
- }
108
-
109
- .manage-btn:hover {
110
- color: var(--clr-accent, #50fa7b);
111
- transform: rotate(45deg);
112
- }
@@ -1,11 +0,0 @@
1
- <div id="container" class="header-widget-container">
2
- <!-- Active Identity Pill -->
3
- <div id="active-identity-pill" class="identity-pill hidden">
4
- <div id="identity-avatar" class="avatar-circle">-</div>
5
- <select id="identity-selector" class="identity-select" title="Switch active identity"></select>
6
- <button id="btn-manage-identities" class="manage-btn" title="Manage Identities">⚙️</button>
7
- </div>
8
-
9
- <!-- Fallback Action Button -->
10
- <button id="btn-create-identity" class="action-btn hidden" title="No active identity. Click to manage.">No Active Identity</button>
11
- </div>
@@ -1,439 +0,0 @@
1
- import thisCss from "./identity-header.css";
2
- import thisHtml from "./identity-header.html";
3
- import styleCss from "../../style.css";
4
-
5
- import { IbGibAddr } from "@ibgib/ts-gib/dist/types.mjs";
6
- import { IbGib_V1 } from "@ibgib/ts-gib/dist/V1/types.mjs";
7
- import { getIbGibAddr } from "@ibgib/ts-gib/dist/helper.mjs";
8
- import { ROOT_ADDR } from "@ibgib/ts-gib/dist/V1/constants.mjs";
9
- import { extractErrorMsg } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
10
- import {
11
- IbGibDynamicComponentMetaBase, IbGibDynamicComponentInstanceBase,
12
- } from "@ibgib/web-gib/dist/ui/component/ibgib-dynamic-component-bases.mjs";
13
- import {
14
- ElementsBase, IbGibDynamicComponentInstance,
15
- IbGibDynamicComponentInstanceInitOpts,
16
- } from "@ibgib/web-gib/dist/ui/component/component-types.mjs";
17
- import { SettingsType } from "@ibgib/web-gib/dist/common/settings/settings-constants.mjs";
18
- import { Settings_General } from "@ibgib/web-gib/dist/common/settings/settings-types.mjs";
19
-
20
- import { getComponentCtorArg, getIbGibGlobalThis_SpaceGib } from "../../helpers.web.mjs";
21
- import { APP_CONFIG } from "../../constants.mjs";
22
- import { getSpaceGibShellSvc } from "../../ui/shell/space-gib-shell-service.mjs";
23
- import { devLog } from "../../dev-tools.mjs";
24
- import { KeystoneService_V1 } from "@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs";
25
- import { KeystoneIbGib_V1 } from "@ibgib/core-gib/dist/keystone/keystone-types.mjs";
26
- import { getDeterministicColorInfo } from "@ibgib/web-gib/dist/helpers.mjs";
27
- import { EVENT_IBGIB_IDENTITY_REQUEST_CHANGE, EVENT_IBGIB_IDENTITY_CHANGED } from "@ibgib/web-gib/dist/ui/ui-constants.mjs";
28
-
29
- export const IDENTITY_HEADER_COMPONENT_NAME = 'ibgib-identity-header';
30
-
31
- /**
32
- * Metadata for the Identity Header component.
33
- */
34
- export class IdentityHeaderComponentMeta extends IbGibDynamicComponentMetaBase {
35
- protected lc: string = `[IdentityHeaderComponentMeta]`;
36
-
37
- routeRegExp?: RegExp = new RegExp(`^${IDENTITY_HEADER_COMPONENT_NAME}$`);
38
- componentName = IDENTITY_HEADER_COMPONENT_NAME;
39
-
40
- constructor() {
41
- super(getComponentCtorArg());
42
- if (!customElements.get(this.componentName)) {
43
- customElements.define(this.componentName, IdentityHeaderComponentInstance);
44
- }
45
- }
46
-
47
- async createInstance({
48
- path,
49
- ibGibAddr
50
- }: {
51
- path: string;
52
- ibGibAddr: IbGibAddr;
53
- }): Promise<IbGibDynamicComponentInstance> {
54
- const component = document.createElement(this.componentName) as IdentityHeaderComponentInstance;
55
- await component.initialize({
56
- ibGibAddr,
57
- meta: this,
58
- html: thisHtml,
59
- css: [styleCss, thisCss],
60
- });
61
- return component;
62
- }
63
- }
64
-
65
- /**
66
- * References to DOM elements within the component's shadow root.
67
- */
68
- interface IdentityHeaderElements extends ElementsBase {
69
- containerEl: HTMLDivElement;
70
- activeIdentityPillEl: HTMLDivElement;
71
- identitySelectorEl: HTMLSelectElement;
72
- btnManageIdentitiesEl: HTMLButtonElement;
73
- btnCreateIdentityEl: HTMLButtonElement;
74
- identityAvatarEl: HTMLDivElement;
75
- }
76
-
77
- /**
78
- * Concrete implementation of the Identity Header component.
79
- */
80
- export class IdentityHeaderComponentInstance
81
- extends IbGibDynamicComponentInstanceBase<IbGib_V1, IdentityHeaderElements>
82
- implements IbGibDynamicComponentInstance<IbGib_V1, IdentityHeaderElements> {
83
-
84
- protected lc: string = `[IdentityHeaderComponentInstance]`;
85
- private activeAddr: string | null = null;
86
- private _onRequestIdentityChange: ((e: any) => void) | null = null;
87
- private keystoneCache: Map<string, { username: string, description: string, isPrimary: boolean }> = new Map();
88
-
89
- constructor() {
90
- super();
91
- }
92
-
93
- private async getKeystoneDetails(addr: string): Promise<{ username: string, description: string, isPrimary: boolean }> {
94
- const cached = this.keystoneCache.get(addr);
95
- if (cached) return cached;
96
-
97
- const metaspace = getIbGibGlobalThis_SpaceGib(APP_CONFIG).metaspace;
98
- if (!metaspace) return { username: '', description: '', isPrimary: false };
99
- const space = await metaspace.getLocalUserSpace({ lock: false });
100
- if (!space) return { username: '', description: '', isPrimary: false };
101
-
102
- try {
103
- const keystoneSvc = new KeystoneService_V1();
104
- const info = await keystoneSvc.getKeystoneCommonInfo({
105
- addr,
106
- metaspace,
107
- space
108
- });
109
- if (info) {
110
- const details = {
111
- username: info.name,
112
- description: info.description,
113
- isPrimary: info.isPrimary
114
- };
115
- this.keystoneCache.set(addr, details);
116
- return details;
117
- }
118
- } catch (err) {
119
- console.warn(`Error getting details for keystone ${addr}: ${extractErrorMsg(err)}`);
120
- }
121
-
122
- return { username: '', description: '', isPrimary: false };
123
- }
124
-
125
-
126
- override async initialize(opts: IbGibDynamicComponentInstanceInitOpts): Promise<void> {
127
- await super.initialize(opts);
128
- }
129
-
130
- override async created(): Promise<void> {
131
- this.elements = {} as IdentityHeaderElements;
132
-
133
- const shadow = this.shadowRoot!;
134
- this.elements.containerEl = shadow.getElementById('container') as HTMLDivElement;
135
- this.elements.activeIdentityPillEl = shadow.getElementById('active-identity-pill') as HTMLDivElement;
136
- this.elements.identitySelectorEl = shadow.getElementById('identity-selector') as HTMLSelectElement;
137
- this.elements.btnManageIdentitiesEl = shadow.getElementById('btn-manage-identities') as HTMLButtonElement;
138
- this.elements.btnCreateIdentityEl = shadow.getElementById('btn-create-identity') as HTMLButtonElement;
139
- this.elements.identityAvatarEl = shadow.getElementById('identity-avatar') as HTMLDivElement;
140
-
141
- // Required contentEl mapping
142
- this.elements.contentEl = this.elements.containerEl;
143
-
144
- this.initHandlers();
145
-
146
- // Subscribe to global active identity request changes
147
- this._onRequestIdentityChange = (e: any) => this.handleRequestIdentityChange(e);
148
- window.addEventListener(EVENT_IBGIB_IDENTITY_REQUEST_CHANGE, this._onRequestIdentityChange);
149
-
150
- if (this.ibGibAddr === ROOT_ADDR || !this.ibGib) {
151
- await this.loadKeystonesIndex();
152
- } else {
153
- await this.initSettings();
154
- }
155
- await this.renderUI();
156
- }
157
-
158
- private async loadKeystonesIndex(): Promise<void> {
159
- const lc = `${this.lc}[loadKeystonesIndex]`;
160
- try {
161
- const metaspace = getIbGibGlobalThis_SpaceGib(APP_CONFIG).metaspace;
162
- if (!metaspace) { return; }
163
- const space = await metaspace.getLocalUserSpace({ lock: false });
164
- if (!space) { return; }
165
- const keystonesIndex = await metaspace.getSpecialIbGib({
166
- type: "keystones",
167
- space,
168
- initialize: true,
169
- });
170
- if (keystonesIndex) {
171
- this.ibGibAddr = getIbGibAddr({ ibGib: keystonesIndex });
172
- await this.loadIbGib();
173
- await this.initSettings();
174
- }
175
- } catch (error) {
176
- console.error(`${lc} ${extractErrorMsg(error)}`);
177
- }
178
- }
179
-
180
- override async disconnected(): Promise<void> {
181
- if (this._onRequestIdentityChange) {
182
- window.removeEventListener(EVENT_IBGIB_IDENTITY_REQUEST_CHANGE, this._onRequestIdentityChange);
183
- }
184
- }
185
-
186
- private initHandlers() {
187
- this.elements!.btnCreateIdentityEl.addEventListener('click', () => this.navigateToManager());
188
- this.elements!.btnManageIdentitiesEl.addEventListener('click', (e) => {
189
- e.stopPropagation();
190
- this.navigateToManager();
191
- });
192
- this.elements!.identitySelectorEl.addEventListener('click', (e) => {
193
- e.stopPropagation();
194
- });
195
- this.elements!.identitySelectorEl.addEventListener('change', () => {
196
- const selectedAddr = this.elements!.identitySelectorEl.value;
197
- if (selectedAddr) {
198
- window.dispatchEvent(new CustomEvent(EVENT_IBGIB_IDENTITY_REQUEST_CHANGE, {
199
- detail: { activeIdentityAddr: selectedAddr },
200
- bubbles: true,
201
- composed: true
202
- }));
203
- }
204
- });
205
- }
206
-
207
- private navigateToManager() {
208
- const shellSvc = getSpaceGibShellSvc();
209
- // Route to center view identity manager
210
- shellSvc.showIdentityManager();
211
- }
212
-
213
- /**
214
- * Resolves the active identity from settings and verifies it exists in the keystones index.
215
- */
216
- private async resolveActiveIdentity() {
217
- const lc = `${this.lc}[resolveActiveIdentity]`;
218
- try {
219
- if (!this.settings) {
220
- this.activeAddr = null;
221
- const globalState = getIbGibGlobalThis_SpaceGib(APP_CONFIG);
222
- globalState.identity = undefined;
223
- return;
224
- }
225
- const generalSettings = await this.getSettings<Settings_General>({
226
- settingsType: SettingsType.general,
227
- useCase: 'current',
228
- });
229
- const activeAddrInSettings = (generalSettings as any)?.activeIdentityAddr;
230
-
231
- // Verify it is actually one of the registered keystones in the index relations
232
- const registeredKeystones = this.ibGib?.rel8ns?.keystone ?? [];
233
- const detailsPromises = registeredKeystones.map(async addr => {
234
- const details = await this.getKeystoneDetails(addr);
235
- return { addr, isPrimary: details?.isPrimary ?? false };
236
- });
237
- const resolvedDetails = await Promise.all(detailsPromises);
238
- const primaryKeystones = resolvedDetails
239
- .filter(item => item.isPrimary)
240
- .map(item => item.addr);
241
-
242
- if (activeAddrInSettings && primaryKeystones.includes(activeAddrInSettings)) {
243
- this.activeAddr = activeAddrInSettings;
244
- } else if (primaryKeystones.length > 0) {
245
- this.activeAddr = primaryKeystones[0];
246
- } else {
247
- this.activeAddr = null;
248
- }
249
-
250
- // Sync with globalState.identity
251
- const globalState = getIbGibGlobalThis_SpaceGib(APP_CONFIG);
252
- if (this.activeAddr) {
253
- const metaspace = globalState.metaspace;
254
- if (metaspace) {
255
- const space = await metaspace.getLocalUserSpace({ lock: false });
256
- if (space) {
257
- const res = await metaspace.get({ addr: this.activeAddr, space });
258
- if (res.success && res.ibGibs && res.ibGibs.length > 0) {
259
- const domainIdentity = res.ibGibs[0] as KeystoneIbGib_V1;
260
-
261
- // Find delegate with the sync allowed verb
262
- let syncDelegateIdentity: KeystoneIbGib_V1 | undefined;
263
- const delegates = domainIdentity.data?.delegates;
264
- if (delegates) {
265
- for (const delegateInfo of Object.values(delegates)) {
266
- if (delegateInfo.allowedVerbs?.includes('sync^gib') || (!delegateInfo.allowedVerbs && delegateInfo.delegateTjpAddr)) {
267
- // Fetch the delegate's latest tip from space
268
- const delegateLatestAddr = await metaspace.getLatestAddr({
269
- addr: delegateInfo.delegateTjpAddr,
270
- space
271
- });
272
- if (delegateLatestAddr) {
273
- const resDelegate = await metaspace.get({ addr: delegateLatestAddr, space });
274
- if (resDelegate.success && resDelegate.ibGibs && resDelegate.ibGibs.length > 0) {
275
- syncDelegateIdentity = resDelegate.ibGibs[0] as KeystoneIbGib_V1;
276
- break;
277
- }
278
- }
279
- }
280
- }
281
- }
282
-
283
- globalState.identity = {
284
- resolved: true,
285
- authenticated: true,
286
- domainIdentity,
287
- syncDelegateIdentity
288
- };
289
- }
290
- }
291
- }
292
- } else {
293
- globalState.identity = {
294
- resolved: false,
295
- authenticated: false
296
- };
297
- }
298
- } catch (error) {
299
- console.error(`${lc} ${extractErrorMsg(error)}`);
300
- this.activeAddr = null;
301
- const globalState = getIbGibGlobalThis_SpaceGib(APP_CONFIG) as any;
302
- globalState.identity = undefined;
303
- }
304
- }
305
-
306
- protected override async renderUI(): Promise<void> {
307
- if (!this.elements) { return; }
308
-
309
- // Double check state on render
310
- await this.resolveActiveIdentity();
311
-
312
- const keystones = this.ibGib?.rel8ns?.keystone ?? [];
313
- const detailsPromises = keystones.map(async addr => {
314
- const details = await this.getKeystoneDetails(addr);
315
- return { addr, isPrimary: details?.isPrimary ?? false };
316
- });
317
- const resolvedDetails = await Promise.all(detailsPromises);
318
- const primaryKeystones = resolvedDetails
319
- .filter(item => item.isPrimary)
320
- .map(item => item.addr);
321
-
322
- if (this.activeAddr && primaryKeystones.length > 0) {
323
- this.elements.activeIdentityPillEl.classList.remove('hidden');
324
- this.elements.btnCreateIdentityEl.classList.add('hidden');
325
-
326
- const addr = this.activeAddr;
327
-
328
- // Populate the dropdown selector
329
- this.elements.identitySelectorEl.innerHTML = '';
330
- for (const kAddr of primaryKeystones) {
331
- const option = document.createElement('option');
332
- option.value = kAddr;
333
-
334
- let displayAddr = kAddr;
335
- if (displayAddr.length > 14) {
336
- displayAddr = displayAddr.substring(0, 7) + '...' + displayAddr.substring(displayAddr.length - 5);
337
- }
338
- option.textContent = displayAddr;
339
-
340
- // Load details asynchronously so we don't block
341
- this.getKeystoneDetails(kAddr).then(details => {
342
- if (details.username) {
343
- let name = details.username;
344
- if (name.length > 14) {
345
- name = name.substring(0, 11) + '...';
346
- }
347
- option.textContent = name;
348
- }
349
- }).catch(err => { });
350
-
351
- this.elements.identitySelectorEl.appendChild(option);
352
- }
353
- this.elements.identitySelectorEl.value = addr;
354
-
355
- // Render active avatar
356
- this.elements.identityAvatarEl.textContent = '-';
357
- this.elements.identityAvatarEl.style.backgroundColor = 'var(--clr-accent)';
358
- this.elements.identityAvatarEl.style.color = '#11111b';
359
-
360
- // Load details dynamically for the active identity
361
- const details = await this.getKeystoneDetails(addr);
362
-
363
- // First letter of username, or fallback to first char of address (or 'A')
364
- let letter = '-';
365
- if (details.username) {
366
- letter = details.username.charAt(0).toUpperCase();
367
- } else {
368
- const match = addr.match(/[a-zA-Z]/);
369
- letter = match ? match[0].toUpperCase() : 'I';
370
- }
371
- if (!this.elements) { throw new Error(`(UNEXPECTED) this.elements falsy? (E: fd6bfa87c968a38c4860588818c3cd26)`); }
372
-
373
- this.elements.identityAvatarEl.textContent = letter;
374
-
375
- // Colorize avatar deterministically based on cryptographic gib
376
- const colorInfo = getDeterministicColorInfo({ ibGibAddr: addr });
377
- const bg = colorInfo.tjpColor || colorInfo.punctiliarColor;
378
- const fg = colorInfo.tjpColorContrast || colorInfo.punctiliarColorContrast;
379
- this.elements.identityAvatarEl.style.backgroundColor = bg;
380
- this.elements.identityAvatarEl.style.color = fg;
381
-
382
- // Title with full details
383
- const titleParts: string[] = [];
384
- if (details.username) {
385
- titleParts.push(`User: ${details.username}`);
386
- }
387
- if (details.description) {
388
- const desc = details.description.length > 100
389
- ? details.description.substring(0, 97) + '...'
390
- : details.description;
391
- titleParts.push(`Desc: ${desc}`);
392
- }
393
- titleParts.push(`Addr: ${addr}`);
394
- this.elements.activeIdentityPillEl.title = titleParts.join('\n');
395
- } else {
396
- this.elements.activeIdentityPillEl.classList.add('hidden');
397
- this.elements.btnCreateIdentityEl.classList.remove('hidden');
398
- }
399
- }
400
-
401
- private async handleRequestIdentityChange(e: any) {
402
- const lc = `${this.lc}[handleRequestIdentityChange]`;
403
- const addr = e.detail?.activeIdentityAddr;
404
- if (!addr) { return; }
405
- devLog(`${lc} Request to change active identity to: ${addr}`);
406
- try {
407
- if (!this.settings) { return; }
408
- const generalSettings = await this.getSettings<Settings_General>({
409
- settingsType: SettingsType.general,
410
- useCase: 'current',
411
- }) ?? { type: 'general' };
412
-
413
- (generalSettings as any).activeIdentityAddr = addr;
414
-
415
- await this.updateSettings({
416
- settingsType: SettingsType.general,
417
- useCase: 'current',
418
- newSectionInfo: generalSettings,
419
- });
420
-
421
- await this.resolveActiveIdentity();
422
- await this.renderUI();
423
-
424
- // Dispatch EVENT_IBGIB_IDENTITY_CHANGED
425
- window.dispatchEvent(new CustomEvent(EVENT_IBGIB_IDENTITY_CHANGED, {
426
- detail: { activeIdentityAddr: addr },
427
- bubbles: true,
428
- composed: true
429
- }));
430
- devLog(`${lc} Successfully changed active identity settings to: ${addr}`);
431
- } catch (error) {
432
- console.error(`${lc} Failed to switch active identity: ${extractErrorMsg(error)}`);
433
- }
434
- }
435
-
436
- override async handleContextUpdated(): Promise<void> {
437
- await this.renderUI();
438
- }
439
- }