@ibgib/web-gib 0.0.52 → 0.0.55
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/CHANGELOG.md +7 -0
- package/dist/AUTO-GENERATED-version.d.mts +1 -1
- package/dist/AUTO-GENERATED-version.mjs +1 -1
- package/dist/api/commands/chat/hello-world.mjs.map +1 -1
- package/dist/api/commands/command-constants.d.mts +4 -4
- package/dist/api/commands/command-constants.d.mts.map +1 -1
- package/dist/api/commands/command-service-v1.d.mts.map +1 -1
- package/dist/api/commands/command-service-v1.mjs.map +1 -1
- package/dist/api/commands/ibgib/get-ibgibs.d.mts.map +1 -1
- package/dist/api/commands/ibgib/get-ibgibs.mjs.map +1 -1
- package/dist/api/ibgib-api-bridge.d.mts +81 -0
- package/dist/api/ibgib-api-bridge.d.mts.map +1 -0
- package/dist/api/ibgib-api-bridge.mjs +259 -0
- package/dist/api/ibgib-api-bridge.mjs.map +1 -0
- package/dist/app-bootstrap/init-orchestration.d.mts +1 -1
- package/dist/app-bootstrap/init-orchestration.d.mts.map +1 -1
- package/dist/app-bootstrap/init-orchestration.mjs +17 -3
- package/dist/app-bootstrap/init-orchestration.mjs.map +1 -1
- package/dist/assets/fullscreen-dialog.html +18 -0
- package/dist/assumptions.respec.mjs.map +1 -1
- package/dist/common/settings/settings-constants.d.mts.map +1 -1
- package/dist/helpers.d.mts.map +1 -1
- package/dist/helpers.mjs.map +1 -1
- package/dist/helpers.web.d.mts.map +1 -1
- package/dist/helpers.web.mjs.map +1 -1
- package/dist/helpers.web.respec.mjs.map +1 -1
- package/dist/identity/keystone-sync-service.d.mts +37 -0
- package/dist/identity/keystone-sync-service.d.mts.map +1 -0
- package/dist/identity/keystone-sync-service.mjs +211 -0
- package/dist/identity/keystone-sync-service.mjs.map +1 -0
- package/dist/identity/sso/sso-custodian-service.d.mts.map +1 -1
- package/dist/identity/sso/sso-custodian-service.mjs.map +1 -1
- package/dist/identity/sso/sso-custodian-service.respec.mjs.map +1 -1
- package/dist/index.d.mts +17 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +21 -26
- package/dist/index.mjs.map +1 -1
- package/dist/storage/storage-helpers.web.mjs.map +1 -1
- package/dist/ui/component/common-component-styles.css +270 -0
- package/dist/ui/component/ibgib-component-service.d.mts.map +1 -1
- package/dist/ui/component/ibgib-dynamic-component-bases.d.mts.map +1 -1
- package/dist/ui/component/ibgib-dynamic-component-bases.mjs.map +1 -1
- package/dist/ui/component/identity/add-device/add-device.css +133 -0
- package/dist/ui/component/identity/add-device/add-device.d.mts +49 -0
- package/dist/ui/component/identity/add-device/add-device.d.mts.map +1 -0
- package/dist/ui/component/identity/add-device/add-device.html +52 -0
- package/dist/ui/component/identity/add-device/add-device.mjs +321 -0
- package/dist/ui/component/identity/add-device/add-device.mjs.map +1 -0
- package/dist/ui/component/identity/identity-header/identity-header.css +317 -0
- package/dist/ui/component/identity/identity-header/identity-header.d.mts +85 -0
- package/dist/ui/component/identity/identity-header/identity-header.d.mts.map +1 -0
- package/dist/ui/component/identity/identity-header/identity-header.html +72 -0
- package/dist/ui/component/identity/identity-header/identity-header.mjs +546 -0
- package/dist/ui/component/identity/identity-header/identity-header.mjs.map +1 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.css +178 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.d.mts +76 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.d.mts.map +1 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.html +19 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.mjs +591 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.mjs.map +1 -0
- package/dist/ui/component/identity/index.d.mts +17 -0
- package/dist/ui/component/identity/index.d.mts.map +1 -0
- package/dist/ui/component/identity/index.mjs +34 -0
- package/dist/ui/component/identity/index.mjs.map +1 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.css +97 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.d.mts +58 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.d.mts.map +1 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.html +51 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs +410 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs.map +1 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.css +621 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.d.mts +98 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.d.mts.map +1 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.html +154 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.mjs +1377 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.mjs.map +1 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.css +46 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.d.mts +64 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.d.mts.map +1 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.html +15 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.mjs +300 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.mjs.map +1 -0
- package/dist/ui/component/identity/remove-device/remove-device.css +118 -0
- package/dist/ui/component/identity/remove-device/remove-device.d.mts +50 -0
- package/dist/ui/component/identity/remove-device/remove-device.d.mts.map +1 -0
- package/dist/ui/component/identity/remove-device/remove-device.html +31 -0
- package/dist/ui/component/identity/remove-device/remove-device.mjs +188 -0
- package/dist/ui/component/identity/remove-device/remove-device.mjs.map +1 -0
- package/dist/ui/ui-constants.d.mts +1 -0
- package/dist/ui/ui-constants.d.mts.map +1 -1
- package/dist/ui/ui-constants.mjs +1 -0
- package/dist/ui/ui-constants.mjs.map +1 -1
- package/dist/ui/ui-types.d.mts +7 -0
- package/dist/ui/ui-types.d.mts.map +1 -1
- package/dist/witness/agent/agent-constants.d.mts.map +1 -1
- package/dist/witness/agent/agent-helpers.mjs.map +1 -1
- package/dist/witness/agent/agent-one-file.d.mts.map +1 -1
- package/dist/witness/agent/agent-one-file.mjs.map +1 -1
- package/dist/witness/agent/agents-service-v1.d.mts.map +1 -1
- package/dist/witness/agent/agents-service-v1.mjs.map +1 -1
- package/dist/witness/agent/gemini/agent-witness-gemini-v1.d.mts.map +1 -1
- package/dist/witness/agent/gemini/gemini-agent-factory.d.mts.map +1 -1
- package/dist/witness/live-proxy-ibgib/live-proxy-ibgib-one-file.d.mts.map +1 -1
- package/dist/witness/live-proxy-ibgib/live-proxy-ibgib-one-file.mjs.map +1 -1
- package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace-helper.mjs.map +1 -1
- package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.d.mts +4 -0
- package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.d.mts.map +1 -1
- package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mjs +40 -1
- package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mjs.map +1 -1
- package/dist/witness/space/web-filesystem-space/web-filesystem-space-types.d.mts.map +1 -1
- package/dist/witness/space/web-filesystem-space/web-filesystem-space-v1.d.mts.map +1 -1
- package/package.json +2 -2
- package/src/AUTO-GENERATED-version.mts +1 -1
- package/src/api/ibgib-api-bridge.mts +292 -0
- package/src/app-bootstrap/init-orchestration.mts +17 -6
- package/src/custom.d.ts +11 -0
- package/src/identity/keystone-sync-service.mts +257 -0
- package/src/index.mts +24 -25
- package/src/ui/component/README.md +82 -5
- package/src/ui/component/common-component-styles.css +270 -0
- package/src/ui/component/identity/add-device/add-device.css +133 -0
- package/src/ui/component/identity/add-device/add-device.html +52 -0
- package/src/ui/component/identity/add-device/add-device.mts +397 -0
- package/src/ui/component/identity/identity-header/IMPLEMENTATION.md +45 -0
- package/src/ui/component/identity/identity-header/identity-header.css +317 -0
- package/src/ui/component/identity/identity-header/identity-header.html +72 -0
- package/src/ui/component/identity/identity-header/identity-header.mts +651 -0
- package/src/ui/component/identity/identity-manager/IMPLEMENTATION.md +100 -0
- package/src/ui/component/identity/identity-manager/identity-manager.css +178 -0
- package/src/ui/component/identity/identity-manager/identity-manager.html +19 -0
- package/src/ui/component/identity/identity-manager/identity-manager.mts +675 -0
- package/src/ui/component/identity/index.mts +36 -0
- package/src/ui/component/identity/keystone-creator/keystone-creator.css +97 -0
- package/src/ui/component/identity/keystone-creator/keystone-creator.html +51 -0
- package/src/ui/component/identity/keystone-creator/keystone-creator.mts +497 -0
- package/src/ui/component/identity/keystone-details/keystone-details.css +621 -0
- package/src/ui/component/identity/keystone-details/keystone-details.html +154 -0
- package/src/ui/component/identity/keystone-details/keystone-details.mts +1506 -0
- package/src/ui/component/identity/keystone-scrubber/SCRUBBER_IMPLEMENTATION.md +33 -0
- package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.css +46 -0
- package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.html +15 -0
- package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.mts +355 -0
- package/src/ui/component/identity/remove-device/remove-device.css +118 -0
- package/src/ui/component/identity/remove-device/remove-device.html +31 -0
- package/src/ui/component/identity/remove-device/remove-device.mts +247 -0
- package/src/ui/ui-constants.mts +1 -0
- package/src/ui/ui-types.mts +8 -0
- package/src/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mts +42 -1
- package/tools/auto-generated-agent-skills/skills/ibgib-dependency-graph/SKILL.md +209 -0
- package/tools/auto-generated-agent-skills/skills/ibgib-implementation-plan/SKILL.md +102 -0
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import thisCss from "./add-device.css";
|
|
2
|
+
import thisHtml from "./add-device.html";
|
|
3
|
+
import commonComponentStylesCss from "../../common-component-styles.css";
|
|
4
|
+
|
|
5
|
+
import { delay, extractErrorMsg, getUUID } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
|
|
6
|
+
import { IbGibAddr } from "@ibgib/ts-gib/dist/types.mjs";
|
|
7
|
+
import { IbGib_V1 } from "@ibgib/ts-gib/dist/V1/types.mjs";
|
|
8
|
+
import { getIbGibAddr } from "@ibgib/ts-gib/dist/helper.mjs";
|
|
9
|
+
import { getGibInfo } from "@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs";
|
|
10
|
+
import { KeystoneService_V1 } from "@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs";
|
|
11
|
+
import { KeystoneProfileBuilder } from "@ibgib/core-gib/dist/keystone/policy/keystone-profile-builder.mjs";
|
|
12
|
+
import { KeystoneIbGib_V1 } from "@ibgib/core-gib/dist/keystone/keystone-types.mjs";
|
|
13
|
+
import { KEYSTONE_VERB_SYNC, KEYSTONE_VERB_CONNECT, KEYSTONE_USERNAME_REGEXP } from "@ibgib/core-gib/dist/keystone/keystone-constants.mjs";
|
|
14
|
+
import { deriveDelegateSecret } from "@ibgib/core-gib/dist/keystone/strategy/hash-reveal-v1/hash-reveal-v1.mjs";
|
|
15
|
+
import { getTimelinesGroupedByTjp, toDto } from "@ibgib/core-gib/dist/common/other/ibgib-helper.mjs";
|
|
16
|
+
import { updateSpecialIndex } from "@ibgib/core-gib/dist/timeline/timeline-api.mjs";
|
|
17
|
+
import { getApiBridge } from "../../../../api/ibgib-api-bridge.mjs";
|
|
18
|
+
|
|
19
|
+
import { getGlobalMetaspace_waitIfNeeded } from "../../../../helpers.mjs";
|
|
20
|
+
import {
|
|
21
|
+
IbGibDynamicComponentMetaBase, IbGibFormInstanceBase,
|
|
22
|
+
} from "../../ibgib-dynamic-component-bases.mjs";
|
|
23
|
+
import {
|
|
24
|
+
ElementsBase, IbGibDynamicComponentInstance,
|
|
25
|
+
IbGibDynamicComponentInstanceInitOpts,
|
|
26
|
+
} from "../../component-types.mjs";
|
|
27
|
+
import { getComponentCtorArg } from "../../../../app-bootstrap/init-orchestration.mjs";
|
|
28
|
+
import { EVENT_IBGIB_IDENTITY_REQUEST_CHANGE, EVENT_IBGIB_UI_MESSAGE } from "../../../ui-constants.mjs";
|
|
29
|
+
|
|
30
|
+
export const ADD_DEVICE_COMPONENT_NAME = 'ibgib-add-device';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Metadata for the Add Device / Pairing component.
|
|
34
|
+
*/
|
|
35
|
+
export class AddDeviceComponentMeta extends IbGibDynamicComponentMetaBase {
|
|
36
|
+
protected lc: string = `[AddDeviceComponentMeta]`;
|
|
37
|
+
|
|
38
|
+
routeRegExp?: RegExp = new RegExp(`^${ADD_DEVICE_COMPONENT_NAME}$`);
|
|
39
|
+
componentName = ADD_DEVICE_COMPONENT_NAME;
|
|
40
|
+
|
|
41
|
+
constructor() {
|
|
42
|
+
super(getComponentCtorArg());
|
|
43
|
+
if (!customElements.get(this.componentName)) {
|
|
44
|
+
customElements.define(this.componentName, AddDeviceComponentInstance);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async createInstance({
|
|
49
|
+
path,
|
|
50
|
+
ibGibAddr
|
|
51
|
+
}: {
|
|
52
|
+
path: string;
|
|
53
|
+
ibGibAddr: IbGibAddr;
|
|
54
|
+
}): Promise<IbGibDynamicComponentInstance> {
|
|
55
|
+
const component = document.createElement(this.componentName) as AddDeviceComponentInstance;
|
|
56
|
+
await component.initialize({
|
|
57
|
+
ibGibAddr,
|
|
58
|
+
meta: this,
|
|
59
|
+
html: thisHtml,
|
|
60
|
+
css: [commonComponentStylesCss, thisCss],
|
|
61
|
+
});
|
|
62
|
+
return component;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
interface AddDeviceElements extends ElementsBase {
|
|
67
|
+
containerEl: HTMLDivElement;
|
|
68
|
+
titleEl: HTMLHeadingElement;
|
|
69
|
+
inputIdentifier: HTMLInputElement;
|
|
70
|
+
inputDeviceTag: HTMLInputElement;
|
|
71
|
+
inputPassphrase: HTMLInputElement;
|
|
72
|
+
checkboxMakeActive: HTMLInputElement;
|
|
73
|
+
btnAddDeviceEl: HTMLButtonElement;
|
|
74
|
+
statusArea: HTMLDivElement;
|
|
75
|
+
statusText: HTMLParagraphElement;
|
|
76
|
+
resultAreaEl: HTMLDivElement;
|
|
77
|
+
delegateAddrEl: HTMLElement;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Concrete implementation of the Add Device / Pairing component.
|
|
82
|
+
*/
|
|
83
|
+
export class AddDeviceComponentInstance
|
|
84
|
+
extends IbGibFormInstanceBase<IbGib_V1, AddDeviceElements>
|
|
85
|
+
implements IbGibDynamicComponentInstance<IbGib_V1, AddDeviceElements> {
|
|
86
|
+
|
|
87
|
+
protected lc: string = `[AddDeviceComponentInstance]`;
|
|
88
|
+
|
|
89
|
+
constructor() {
|
|
90
|
+
super();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
override async initialize(opts: IbGibDynamicComponentInstanceInitOpts): Promise<void> {
|
|
94
|
+
await super.initialize(opts);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
override async created(): Promise<void> {
|
|
98
|
+
this.elements = {} as AddDeviceElements;
|
|
99
|
+
|
|
100
|
+
this.elements.containerEl = this.shadowRoot!.getElementById('container') as HTMLDivElement;
|
|
101
|
+
this.elements.titleEl = this.shadowRoot!.getElementById('title') as HTMLHeadingElement;
|
|
102
|
+
this.elements.inputIdentifier = this.shadowRoot!.getElementById('input-identifier') as HTMLInputElement;
|
|
103
|
+
this.elements.inputDeviceTag = (this.shadowRoot!.getElementById('input-device-tag') || this.shadowRoot!.getElementById('input-device-name')) as HTMLInputElement;
|
|
104
|
+
this.elements.inputPassphrase = this.shadowRoot!.getElementById('input-passphrase') as HTMLInputElement;
|
|
105
|
+
this.elements.checkboxMakeActive = this.shadowRoot!.getElementById('checkbox-make-active') as HTMLInputElement;
|
|
106
|
+
this.elements.btnAddDeviceEl = this.shadowRoot!.getElementById('btn-add-device') as HTMLButtonElement;
|
|
107
|
+
this.elements.statusArea = this.shadowRoot!.getElementById('status-area') as HTMLDivElement;
|
|
108
|
+
this.elements.statusText = this.shadowRoot!.getElementById('status-text') as HTMLParagraphElement;
|
|
109
|
+
this.elements.resultAreaEl = this.shadowRoot!.getElementById('result-area') as HTMLDivElement;
|
|
110
|
+
this.elements.delegateAddrEl = this.shadowRoot!.getElementById('delegate-addr') as HTMLElement;
|
|
111
|
+
|
|
112
|
+
this.elements.contentEl = this.elements.containerEl;
|
|
113
|
+
|
|
114
|
+
this.initHandlers();
|
|
115
|
+
await this.renderUI();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
override async disconnected(): Promise<void> {
|
|
119
|
+
// cleanup if needed
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private initHandlers() {
|
|
123
|
+
this.elements!.btnAddDeviceEl.addEventListener('click', () => this.handleAddDevice());
|
|
124
|
+
|
|
125
|
+
this.shadowRoot!.getElementById('btn-switch-create-account')?.addEventListener('click', (e) => {
|
|
126
|
+
e.preventDefault();
|
|
127
|
+
window.dispatchEvent(new CustomEvent(EVENT_IBGIB_UI_MESSAGE, {
|
|
128
|
+
detail: { action: 'show-keystone-creator' },
|
|
129
|
+
bubbles: true,
|
|
130
|
+
composed: true
|
|
131
|
+
}));
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
this.elements!.inputIdentifier.addEventListener('input', () => {
|
|
135
|
+
this.elements!.inputIdentifier.classList.remove('invalid');
|
|
136
|
+
});
|
|
137
|
+
this.elements!.inputDeviceTag.addEventListener('input', () => {
|
|
138
|
+
this.elements!.inputDeviceTag.classList.remove('invalid');
|
|
139
|
+
});
|
|
140
|
+
this.elements!.inputPassphrase.addEventListener('input', () => {
|
|
141
|
+
this.elements!.inputPassphrase.classList.remove('invalid');
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private setButtonLoading(isLoading: boolean) {
|
|
146
|
+
if (this.elements?.btnAddDeviceEl) {
|
|
147
|
+
this.elements.btnAddDeviceEl.disabled = isLoading;
|
|
148
|
+
this.elements.btnAddDeviceEl.textContent = isLoading ? 'Pairing...' : 'Pair & Add Device';
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Executes the Phase 1 Add-Device pairing orchestration flow.
|
|
154
|
+
*/
|
|
155
|
+
protected async handleAddDevice() {
|
|
156
|
+
const lc = `${this.lc}[${this.handleAddDevice.name}]`;
|
|
157
|
+
try {
|
|
158
|
+
const humanEyeDelay = 500;
|
|
159
|
+
this.setStatus("Initializing device pairing...", "info");
|
|
160
|
+
|
|
161
|
+
const identifier = this.elements!.inputIdentifier.value.trim();
|
|
162
|
+
this.elements!.inputIdentifier.value = identifier;
|
|
163
|
+
if (!identifier) {
|
|
164
|
+
this.elements!.inputIdentifier.classList.add('invalid');
|
|
165
|
+
this.setStatus("Please enter a registered username or email.", "error");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const deviceTag = this.elements!.inputDeviceTag.value.trim();
|
|
170
|
+
this.elements!.inputDeviceTag.value = deviceTag;
|
|
171
|
+
if (!deviceTag || !KEYSTONE_USERNAME_REGEXP.test(deviceTag)) {
|
|
172
|
+
this.elements!.inputDeviceTag.classList.add('invalid');
|
|
173
|
+
this.setStatus("Please enter a valid Device Tag / Name (e.g. 'work-laptop').", "error");
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const masterSecret = this.elements!.inputPassphrase.value.trim();
|
|
178
|
+
this.elements!.inputPassphrase.value = masterSecret;
|
|
179
|
+
if (!masterSecret) {
|
|
180
|
+
this.elements!.inputPassphrase.classList.add('invalid');
|
|
181
|
+
this.setStatus("Please enter your master passphrase.", "error");
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
this.setButtonLoading(true);
|
|
186
|
+
this.showBusy({
|
|
187
|
+
isBusy: true,
|
|
188
|
+
title: 'Locating Identity...',
|
|
189
|
+
msg: 'Searching for primary identity...',
|
|
190
|
+
animationEmoji: '🔍'
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const metaspace = await getGlobalMetaspace_waitIfNeeded();
|
|
194
|
+
const space = await metaspace.getLocalUserSpace({});
|
|
195
|
+
if (!space) { throw new Error("No default space found in metaspace."); }
|
|
196
|
+
|
|
197
|
+
const keystoneService = new KeystoneService_V1();
|
|
198
|
+
|
|
199
|
+
// 1a. First attempt to locate primary identity keystone locally in space
|
|
200
|
+
const keystonesIndex = await metaspace.getSpecialIbGib({
|
|
201
|
+
type: "keystones",
|
|
202
|
+
space,
|
|
203
|
+
initialize: true,
|
|
204
|
+
});
|
|
205
|
+
const registeredAddrs: string[] = keystonesIndex?.rel8ns?.keystone ?? [];
|
|
206
|
+
|
|
207
|
+
let primaryKeystone: KeystoneIbGib_V1 | undefined;
|
|
208
|
+
for (const addr of registeredAddrs) {
|
|
209
|
+
const res = await metaspace.get({ addrs: [addr], space });
|
|
210
|
+
const found = res?.ibGibs?.[0] as KeystoneIbGib_V1 | undefined;
|
|
211
|
+
if (found && found.data) {
|
|
212
|
+
const username = found.data.frameDetails?.username ?? '';
|
|
213
|
+
const emails = found.data.emails ?? found.data.frameDetails?.emails ?? [];
|
|
214
|
+
if (username.toLowerCase() === identifier.toLowerCase() || emails.some((e: string) => e.toLowerCase() === identifier.toLowerCase())) {
|
|
215
|
+
primaryKeystone = found;
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// 1b. If not found locally, query server identity index
|
|
222
|
+
if (!primaryKeystone) {
|
|
223
|
+
this.setStatus("Locating identity on server...", "info");
|
|
224
|
+
const resLookup = await getApiBridge().lookupPrimaryKeystone({ identifier });
|
|
225
|
+
if (resLookup.success && resLookup.primaryKeystoneIbGib) {
|
|
226
|
+
const fetchedKeystone = resLookup.primaryKeystoneIbGib as KeystoneIbGib_V1;
|
|
227
|
+
const domainAddr = resLookup.tjpAddr || getIbGibAddr({ ibGib: fetchedKeystone });
|
|
228
|
+
|
|
229
|
+
// Fetch full domain graph from server so local space has all historical keystone frames
|
|
230
|
+
const resGraph = await getApiBridge().getKeystoneGraph(domainAddr);
|
|
231
|
+
if (resGraph.success && resGraph.graph) {
|
|
232
|
+
const graphIbGibs = Object.values(resGraph.graph);
|
|
233
|
+
await metaspace.put({ ibGibs: graphIbGibs, space });
|
|
234
|
+
|
|
235
|
+
// Order timelines by TJP and register each frame in ascending order
|
|
236
|
+
const timelinesMap = getTimelinesGroupedByTjp({ ibGibs: graphIbGibs });
|
|
237
|
+
for (const tjpKey of Object.keys(timelinesMap)) {
|
|
238
|
+
const timeline = timelinesMap[tjpKey];
|
|
239
|
+
for (const frame of timeline) {
|
|
240
|
+
await metaspace.registerNewIbGib({ ibGib: frame, space });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Set primaryKeystone to the latest frame in the domain timeline
|
|
245
|
+
const domainTimeline = timelinesMap[domainAddr] || timelinesMap[Object.keys(timelinesMap)[0]];
|
|
246
|
+
if (domainTimeline && domainTimeline.length > 0) {
|
|
247
|
+
primaryKeystone = domainTimeline[domainTimeline.length - 1] as KeystoneIbGib_V1;
|
|
248
|
+
} else {
|
|
249
|
+
primaryKeystone = fetchedKeystone;
|
|
250
|
+
}
|
|
251
|
+
} else {
|
|
252
|
+
await metaspace.put({ ibGibs: [fetchedKeystone], space });
|
|
253
|
+
await metaspace.registerNewIbGib({ ibGib: fetchedKeystone, space });
|
|
254
|
+
primaryKeystone = fetchedKeystone;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (!primaryKeystone) {
|
|
260
|
+
const msg = `No registered identity found for '${identifier}'. Please check your username/email or create a new account.`;
|
|
261
|
+
console.error(`${lc} ${msg}`);
|
|
262
|
+
this.setStatus(msg, "error");
|
|
263
|
+
this.showBusy({ isBusy: false });
|
|
264
|
+
this.setButtonLoading(false);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const primaryUsername = primaryKeystone.data?.frameDetails?.username ?? 'user';
|
|
269
|
+
|
|
270
|
+
// 2. Generate local device delegate keystone
|
|
271
|
+
this.setStatus("Generating local device delegate...", "info");
|
|
272
|
+
this.showBusy({
|
|
273
|
+
isBusy: true,
|
|
274
|
+
title: 'Generating Keys...',
|
|
275
|
+
msg: 'Generating cryptographic delegate keys for this device...',
|
|
276
|
+
animationEmoji: '🔑'
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const delegateSecret = await deriveDelegateSecret({ masterSecret });
|
|
280
|
+
const delegateBuilder = KeystoneProfileBuilder.buildKeystone('sync')
|
|
281
|
+
.withUsername(`${primaryUsername}-sync-${deviceTag}`)
|
|
282
|
+
.withDescription(`Sync Delegate for ${primaryUsername} on ${deviceTag}`)
|
|
283
|
+
.withDetails({
|
|
284
|
+
client: 'space-gib-web',
|
|
285
|
+
role: 'sync-delegate',
|
|
286
|
+
deviceTag
|
|
287
|
+
});
|
|
288
|
+
const delegateConfigs = await delegateBuilder.compileConfigs();
|
|
289
|
+
|
|
290
|
+
const delegateKeystone = await keystoneService.genesis({
|
|
291
|
+
masterSecret: delegateSecret,
|
|
292
|
+
configs: delegateConfigs,
|
|
293
|
+
metaspace,
|
|
294
|
+
space,
|
|
295
|
+
frameDetails: delegateBuilder.getFrameDetails()
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
const delegateAddr = getIbGibAddr({ ibGib: delegateKeystone });
|
|
299
|
+
console.log(`${lc} Local device delegate generated: ${delegateAddr}`);
|
|
300
|
+
await delay(humanEyeDelay);
|
|
301
|
+
|
|
302
|
+
// 3. Evolve parent primary keystone to register delegate
|
|
303
|
+
this.setStatus("Registering device on primary identity...", "info");
|
|
304
|
+
this.showBusy({
|
|
305
|
+
isBusy: true,
|
|
306
|
+
title: 'Registering Device...',
|
|
307
|
+
msg: 'Updating primary identity with new device delegate...',
|
|
308
|
+
animationEmoji: '📝'
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const evolvedPrimaryKeystone = await keystoneService.registerDelegate({
|
|
312
|
+
parentKeystone: primaryKeystone,
|
|
313
|
+
delegateKeystone,
|
|
314
|
+
masterSecret,
|
|
315
|
+
metaspace,
|
|
316
|
+
space,
|
|
317
|
+
allowedVerbs: [KEYSTONE_VERB_SYNC, KEYSTONE_VERB_CONNECT],
|
|
318
|
+
deviceName: deviceTag,
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
const evolvedPrimaryAddr = getIbGibAddr({ ibGib: evolvedPrimaryKeystone });
|
|
322
|
+
console.log(`${lc} Primary identity evolved with delegate: ${evolvedPrimaryAddr}`);
|
|
323
|
+
await delay(humanEyeDelay);
|
|
324
|
+
|
|
325
|
+
// 4. Post evolved primary keystone + delegate to server
|
|
326
|
+
this.setStatus("Syncing device pairing to server...", "info");
|
|
327
|
+
this.showBusy({
|
|
328
|
+
isBusy: true,
|
|
329
|
+
title: 'Syncing to Server...',
|
|
330
|
+
msg: 'Posting device pairing to server sync node...',
|
|
331
|
+
animationEmoji: '🔄'
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const primaryTjpAddr = getGibInfo({ ibGibAddr: getIbGibAddr({ ibGib: primaryKeystone }) }).tjpGib;
|
|
335
|
+
const domainAddr = primaryTjpAddr ? getIbGibAddr({ ibGib: primaryKeystone }) : getIbGibAddr({ ibGib: primaryKeystone });
|
|
336
|
+
|
|
337
|
+
const resEvolve = await getApiBridge().putEvolveKeystone({
|
|
338
|
+
domainAddr,
|
|
339
|
+
keystoneIbGib: evolvedPrimaryKeystone,
|
|
340
|
+
relatedKeystoneIbGibs: [delegateKeystone]
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
if (!resEvolve.success) {
|
|
344
|
+
const msg = `Server rejected device pairing: ${resEvolve.message}`;
|
|
345
|
+
console.error(`${lc} ${msg}`);
|
|
346
|
+
this.setStatus(msg, "error");
|
|
347
|
+
this.showBusy({ isBusy: false });
|
|
348
|
+
this.setButtonLoading(false);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// 5. Update local keystones index
|
|
353
|
+
this.showBusy({
|
|
354
|
+
isBusy: true,
|
|
355
|
+
title: 'Updating Local Indexes...',
|
|
356
|
+
msg: 'Registering new device in local index...',
|
|
357
|
+
animationEmoji: '💾'
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
await updateSpecialIndex({
|
|
361
|
+
type: "keystones",
|
|
362
|
+
rel8nInfos: [
|
|
363
|
+
{
|
|
364
|
+
rel8nName: "keystone",
|
|
365
|
+
ibGibs: [
|
|
366
|
+
toDto({ ibGib: evolvedPrimaryKeystone }),
|
|
367
|
+
toDto({ ibGib: delegateKeystone })
|
|
368
|
+
],
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
metaspace,
|
|
372
|
+
space,
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
// 6. Set as active identity if checked
|
|
376
|
+
if (this.elements!.checkboxMakeActive.checked) {
|
|
377
|
+
window.dispatchEvent(new CustomEvent(EVENT_IBGIB_IDENTITY_REQUEST_CHANGE, {
|
|
378
|
+
detail: { activeIdentityAddr: evolvedPrimaryAddr },
|
|
379
|
+
bubbles: true,
|
|
380
|
+
composed: true
|
|
381
|
+
}));
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
this.showBusy({ isBusy: false });
|
|
385
|
+
this.setButtonLoading(false);
|
|
386
|
+
this.elements!.delegateAddrEl.innerText = delegateAddr;
|
|
387
|
+
this.elements!.resultAreaEl.classList.remove('collapsed');
|
|
388
|
+
this.setStatus("Device successfully paired!", "success");
|
|
389
|
+
|
|
390
|
+
} catch (error) {
|
|
391
|
+
console.error(`${lc} ${extractErrorMsg(error)}`, error);
|
|
392
|
+
this.setStatus(`Pairing failed: ${extractErrorMsg(error)}`, "error");
|
|
393
|
+
this.showBusy({ isBusy: false });
|
|
394
|
+
this.setButtonLoading(false);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
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.
|