@ibgib/space-gib 0.0.2 → 0.0.4
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 +4 -0
- package/IMPLEMENTATION.md +9 -13
- package/dist/client/bootstrap.mjs +1 -1
- package/dist/client/bootstrap.mjs.map +1 -1
- package/dist/client/chunk-NCXKCVYS.mjs +42 -0
- package/dist/client/chunk-NCXKCVYS.mjs.map +7 -0
- package/dist/client/chunk-ZUEU37Z5.mjs +1920 -0
- package/dist/client/chunk-ZUEU37Z5.mjs.map +7 -0
- package/dist/client/index.html +108 -8
- package/dist/client/index.mjs +1 -1
- package/dist/client/script.mjs +1 -1
- package/dist/client/style.css +466 -61
- package/dist/respec-gib.node.mjs +5 -0
- package/dist/server/server.mjs +815 -316
- package/dist/server/server.mjs.map +4 -4
- package/package.json +6 -6
- package/src/client/AUTO-GENERATED-version.mts +1 -1
- package/src/client/api/space-gib-api-bridge.mts +35 -0
- package/src/client/components/identity-header/IMPLEMENTATION.md +45 -0
- package/src/client/components/identity-header/identity-header.css +74 -0
- package/src/client/components/identity-header/identity-header.html +10 -0
- package/src/client/components/identity-header/identity-header.mts +361 -0
- package/src/client/components/identity-manager/IMPLEMENTATION.md +100 -0
- package/src/client/components/identity-manager/identity-manager.css +467 -0
- package/src/client/components/identity-manager/identity-manager.html +113 -0
- package/src/client/components/identity-manager/identity-manager.mts +767 -0
- package/src/client/components/keystone-creator/keystone-creator.css +2 -76
- package/src/client/components/keystone-creator/keystone-creator.html +41 -26
- package/src/client/components/keystone-creator/keystone-creator.mts +178 -41
- package/src/client/dev-tools/base-tools.mts +252 -0
- package/src/client/dev-tools/common.mts +217 -0
- package/src/client/dev-tools/phase-1.mts +156 -0
- package/src/client/dev-tools/phase-2.mts +143 -0
- package/src/client/dev-tools/phase-3.mts +189 -0
- package/src/client/dev-tools/phase-4-1.mts +197 -0
- package/src/client/dev-tools/phase-4-10.mts +884 -0
- package/src/client/dev-tools/phase-4-2.mts +388 -0
- package/src/client/dev-tools/phase-4-3.mts +391 -0
- package/src/client/dev-tools/phase-4-4.mts +374 -0
- package/src/client/dev-tools/phase-4-5.mts +376 -0
- package/src/client/dev-tools/phase-4-6.mts +273 -0
- package/src/client/dev-tools/phase-4-7.mts +399 -0
- package/src/client/dev-tools/phase-4-8.mts +430 -0
- package/src/client/dev-tools/phase-4-9.mts +398 -0
- package/src/client/dev-tools/phase-4.mts +1302 -0
- package/src/client/dev-tools.mts +55 -1096
- package/src/client/index.html +108 -8
- package/src/client/style.css +466 -61
- package/src/client/ui/shell/space-gib-shell-constants.mts +0 -2
- package/src/client/ui/shell/space-gib-shell-service.mts +82 -10
- package/src/common/common-constants.mts +0 -0
- package/src/common/keystone-policies.json +40 -43
- package/src/common/keystone-policies.mts +4 -6
- package/src/server/path-helper.respec.mts +99 -94
- package/src/server/serve-gib/README.md +9 -0
- package/src/server/serve-gib/handlers/api/keystone/keystone-evolve.handler.mts +1 -1
- package/src/server/serve-gib/handlers/api/keystone/keystone-genesis.handler.mts +1 -1
- package/src/server/serve-gib/handlers/api/keystone/keystone-get.respec.mts +4 -4
- package/src/server/serve-gib/handlers/api/keystone/keystone-post.handler.mts +1 -1
- package/src/server/serve-gib/handlers/ws/sync-upgrade-handler-base.mts +37 -5
- package/src/server/serve-gib/handlers/ws/ws-helper.mts +73 -45
- package/dist/client/chunk-BL2SGXS4.mjs +0 -18994
- package/dist/client/chunk-RDTAT5G4.mjs +0 -235
- package/dist/client/chunk-RDTAT5G4.mjs.map +0 -7
- package/dist/client/chunk-RE7XSMHH.mjs +0 -31
- package/dist/client/chunk-RE7XSMHH.mjs.map +0 -7
- package/dist/client/chunk-YUSGN3J4.mjs +0 -23119
|
@@ -9,11 +9,14 @@ import {
|
|
|
9
9
|
ID_APP_ROOT, ID_HEADER_PANEL, ID_LEFT_PANEL, ID_CENTER_PANEL,
|
|
10
10
|
ID_RIGHT_PANEL, ID_FOOTER_PANEL, ID_LEFT_RESIZER, ID_RIGHT_RESIZER,
|
|
11
11
|
ID_FOOTER_RESIZER, ID_BTN_LEFT_PANEL_TOGGLE, ID_BTN_RIGHT_PANEL_TOGGLE,
|
|
12
|
-
ID_BTN_CREATE_KEYSTONE, ID_CENTER_PANEL_CONTENT
|
|
13
|
-
EVENT_SHELL_READY
|
|
12
|
+
ID_BTN_CREATE_KEYSTONE, ID_CENTER_PANEL_CONTENT
|
|
14
13
|
} from "./space-gib-shell-constants.mjs";
|
|
14
|
+
import { EVENT_IBGIB_SHELL_READY, EVENT_IBGIB_UI_BUSY } from "@ibgib/web-gib/dist/ui/ui-constants.mjs";
|
|
15
|
+
import { showFullscreenDialog, FullscreenDialogController } from "@ibgib/web-gib/dist/ui/ui-helpers.mjs";
|
|
15
16
|
import { PanelState } from "./space-gib-shell-types.mjs";
|
|
16
17
|
import { KeystoneCreatorComponentMeta } from "../../components/keystone-creator/keystone-creator.mjs";
|
|
18
|
+
import { IdentityManagerComponentMeta } from "../../components/identity-manager/identity-manager.mjs";
|
|
19
|
+
import { IdentityHeaderComponentMeta } from "../../components/identity-header/identity-header.mjs";
|
|
17
20
|
|
|
18
21
|
export class SpaceGibShellService {
|
|
19
22
|
private lc: string = `[SpaceGibShellService]`;
|
|
@@ -93,9 +96,66 @@ export class SpaceGibShellService {
|
|
|
93
96
|
// Create Keystone Button
|
|
94
97
|
const btnCreate = document.getElementById(ID_BTN_CREATE_KEYSTONE);
|
|
95
98
|
if (btnCreate) {
|
|
96
|
-
btnCreate.addEventListener('click', () => this.
|
|
99
|
+
btnCreate.addEventListener('click', () => this.showIdentityManager());
|
|
97
100
|
}
|
|
98
101
|
|
|
102
|
+
// Listen for global busy events from components
|
|
103
|
+
let currentBusyOverlay: FullscreenDialogController | undefined;
|
|
104
|
+
let isShellBusy = false;
|
|
105
|
+
window.addEventListener(EVENT_IBGIB_UI_BUSY, (ev: any) => {
|
|
106
|
+
const { isBusy, title, msg, animationEmoji } = ev.detail;
|
|
107
|
+
if (isBusy) {
|
|
108
|
+
isShellBusy = true;
|
|
109
|
+
if (currentBusyOverlay) {
|
|
110
|
+
currentBusyOverlay.update({ title, msg, animationEmoji });
|
|
111
|
+
} else {
|
|
112
|
+
// we use a .then() only because we are within
|
|
113
|
+
// synchronous code.
|
|
114
|
+
showFullscreenDialog({
|
|
115
|
+
title: title || 'Processing...',
|
|
116
|
+
msg: msg || 'Please do not navigate away or refresh.',
|
|
117
|
+
isBusy: true,
|
|
118
|
+
animationEmoji
|
|
119
|
+
}).then((overlay) => {
|
|
120
|
+
if (isShellBusy) {
|
|
121
|
+
currentBusyOverlay = overlay;
|
|
122
|
+
} else {
|
|
123
|
+
overlay.close();
|
|
124
|
+
}
|
|
125
|
+
}).catch((e) => {
|
|
126
|
+
console.error(`${lc}[showFullscreenDialog] ${extractErrorMsg(e)}`)
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
isShellBusy = false;
|
|
131
|
+
if (currentBusyOverlay) {
|
|
132
|
+
currentBusyOverlay.close();
|
|
133
|
+
currentBusyOverlay = undefined;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public async showIdentityManager() {
|
|
144
|
+
const lc = `${this.lc}[${this.showIdentityManager.name}]`;
|
|
145
|
+
try {
|
|
146
|
+
// 2. Instantiate and inject the component
|
|
147
|
+
const componentSvc = await getComponentSvc();
|
|
148
|
+
const component = await componentSvc.getComponentInstance({
|
|
149
|
+
path: 'ibgib-identity-manager',
|
|
150
|
+
ibGibAddr: ROOT_ADDR, // Virtual address for initial render
|
|
151
|
+
useRegExpPrefilter: true,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const centerPanel = document.getElementById(ID_CENTER_PANEL_CONTENT);
|
|
155
|
+
if (centerPanel && component) {
|
|
156
|
+
centerPanel.innerHTML = ''; // Clear hero section
|
|
157
|
+
centerPanel.appendChild(component as any);
|
|
158
|
+
}
|
|
99
159
|
} catch (error) {
|
|
100
160
|
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
101
161
|
}
|
|
@@ -104,19 +164,15 @@ export class SpaceGibShellService {
|
|
|
104
164
|
private async showKeystoneCreator() {
|
|
105
165
|
const lc = `${this.lc}[${this.showKeystoneCreator.name}]`;
|
|
106
166
|
try {
|
|
107
|
-
// 1. Expand side panels (as requested for visual transition)
|
|
108
|
-
if (this.leftPanelState === 'collapsed') { this.toggleLeftPanel(); }
|
|
109
|
-
if (this.rightPanelState === 'collapsed') { this.toggleRightPanel(); }
|
|
110
|
-
|
|
111
167
|
// 2. Instantiate and inject the component
|
|
112
168
|
const componentSvc = await getComponentSvc();
|
|
113
169
|
const component = await componentSvc.getComponentInstance({
|
|
114
|
-
path: '
|
|
170
|
+
path: 'ibgib-keystone-creator',
|
|
115
171
|
ibGibAddr: ROOT_ADDR, // Virtual address for initial render
|
|
116
172
|
useRegExpPrefilter: true,
|
|
117
173
|
});
|
|
118
174
|
|
|
119
|
-
const centerPanel = document.getElementById(
|
|
175
|
+
const centerPanel = document.getElementById(ID_CENTER_PANEL_CONTENT);
|
|
120
176
|
if (centerPanel && component) {
|
|
121
177
|
centerPanel.innerHTML = ''; // Clear hero section
|
|
122
178
|
centerPanel.appendChild(component as any);
|
|
@@ -190,6 +246,8 @@ export class SpaceGibShellService {
|
|
|
190
246
|
try {
|
|
191
247
|
const componentsMeta: IbGibDynamicComponentMeta[] = [
|
|
192
248
|
new KeystoneCreatorComponentMeta(),
|
|
249
|
+
new IdentityManagerComponentMeta(),
|
|
250
|
+
new IdentityHeaderComponentMeta(),
|
|
193
251
|
];
|
|
194
252
|
const componentSvc = await getComponentSvc();
|
|
195
253
|
for (let componentMeta of componentsMeta) {
|
|
@@ -213,7 +271,21 @@ export class SpaceGibShellService {
|
|
|
213
271
|
statusSection.style.display = 'none';
|
|
214
272
|
}
|
|
215
273
|
|
|
216
|
-
|
|
274
|
+
// Mount identity-header component in the header bar
|
|
275
|
+
const componentSvc = await getComponentSvc();
|
|
276
|
+
const identityHeader = await componentSvc.getComponentInstance({
|
|
277
|
+
path: 'ibgib-identity-header',
|
|
278
|
+
ibGibAddr: ROOT_ADDR,
|
|
279
|
+
useRegExpPrefilter: true,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
const headerContainer = document.getElementById('identity-header-container');
|
|
283
|
+
if (headerContainer && identityHeader) {
|
|
284
|
+
headerContainer.innerHTML = '';
|
|
285
|
+
headerContainer.appendChild(identityHeader as any);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
window.dispatchEvent(new CustomEvent(EVENT_IBGIB_SHELL_READY, { detail: { timestamp: Date.now() } }));
|
|
217
289
|
} catch (error) {
|
|
218
290
|
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
219
291
|
}
|
|
File without changes
|
|
@@ -1,64 +1,61 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "../../../../libs/core-gib/
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
"replenish": "top-up",
|
|
7
|
-
"selectSequentially": 2,
|
|
8
|
-
"selectRandomly": 2,
|
|
9
|
-
"targetBindingChars": 5
|
|
10
|
-
},
|
|
11
|
-
"high-security": {
|
|
12
|
-
"size": 2000,
|
|
13
|
-
"replenish": "replace-all",
|
|
14
|
-
"selectSequentially": 5,
|
|
15
|
-
"selectRandomly": 5,
|
|
16
|
-
"targetBindingChars": 16
|
|
17
|
-
},
|
|
18
|
-
"session-connect": {
|
|
19
|
-
"size": 20,
|
|
20
|
-
"replenish": "top-up",
|
|
21
|
-
"selectSequentially": 2,
|
|
22
|
-
"selectRandomly": 2,
|
|
23
|
-
"targetBindingChars": 3
|
|
24
|
-
}
|
|
2
|
+
"$schema": "../../../../libs/core-gib/dist/keystone/policy/schemas/keystone.medium.schema.json",
|
|
3
|
+
"metadata": {
|
|
4
|
+
"name": "Space-Gib Default Identity Policy",
|
|
5
|
+
"securityLevel": "medium"
|
|
25
6
|
},
|
|
26
7
|
"pools": {
|
|
27
8
|
"sync": {
|
|
28
9
|
"id": "sync",
|
|
29
|
-
"allowedVerbs": [
|
|
30
|
-
"sync"
|
|
31
|
-
],
|
|
32
|
-
"behaviorProfile": "standard",
|
|
10
|
+
"allowedVerbs": ["sync"],
|
|
33
11
|
"algo": "SHA-256",
|
|
34
|
-
"rounds": 1
|
|
12
|
+
"rounds": 1,
|
|
13
|
+
"behavior": {
|
|
14
|
+
"size": 200,
|
|
15
|
+
"replenish": "top-up",
|
|
16
|
+
"selectSequentially": 2,
|
|
17
|
+
"selectRandomly": 2,
|
|
18
|
+
"targetBindingCount": 5
|
|
19
|
+
}
|
|
35
20
|
},
|
|
36
21
|
"manage": {
|
|
37
22
|
"id": "manage",
|
|
38
|
-
"allowedVerbs": [
|
|
39
|
-
"manage"
|
|
40
|
-
],
|
|
41
|
-
"behaviorProfile": "high-security",
|
|
23
|
+
"allowedVerbs": ["manage"],
|
|
42
24
|
"algo": "SHA-512",
|
|
43
|
-
"rounds": 10
|
|
25
|
+
"rounds": 10,
|
|
26
|
+
"behavior": {
|
|
27
|
+
"size": 2000,
|
|
28
|
+
"replenish": "replace-all",
|
|
29
|
+
"selectSequentially": 5,
|
|
30
|
+
"selectRandomly": 5,
|
|
31
|
+
"targetBindingCount": 16
|
|
32
|
+
}
|
|
44
33
|
},
|
|
45
34
|
"revoke": {
|
|
46
35
|
"id": "revoke",
|
|
47
|
-
"allowedVerbs": [
|
|
48
|
-
"revoke"
|
|
49
|
-
],
|
|
50
|
-
"behaviorProfile": "high-security",
|
|
36
|
+
"allowedVerbs": ["revoke"],
|
|
51
37
|
"algo": "SHA-512",
|
|
52
|
-
"rounds": 10
|
|
38
|
+
"rounds": 10,
|
|
39
|
+
"behavior": {
|
|
40
|
+
"size": 2000,
|
|
41
|
+
"replenish": "delete-all",
|
|
42
|
+
"selectSequentially": 5,
|
|
43
|
+
"selectRandomly": 5,
|
|
44
|
+
"targetBindingCount": 16
|
|
45
|
+
}
|
|
53
46
|
},
|
|
54
47
|
"connect": {
|
|
55
48
|
"id": "connect",
|
|
56
|
-
"allowedVerbs": [
|
|
57
|
-
"connect"
|
|
58
|
-
],
|
|
59
|
-
"behaviorProfile": "session-connect",
|
|
49
|
+
"allowedVerbs": ["connect"],
|
|
60
50
|
"algo": "SHA-256",
|
|
61
|
-
"rounds": 1
|
|
51
|
+
"rounds": 1,
|
|
52
|
+
"behavior": {
|
|
53
|
+
"size": 20,
|
|
54
|
+
"replenish": "top-up",
|
|
55
|
+
"selectSequentially": 2,
|
|
56
|
+
"selectRandomly": 2,
|
|
57
|
+
"targetBindingCount": 3
|
|
58
|
+
}
|
|
62
59
|
}
|
|
63
60
|
}
|
|
64
61
|
}
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
SESSION_KEYSTONE_POLICY as CORE_SESSION_KEYSTONE_POLICY,
|
|
16
16
|
getConnectChallenge as coreGetConnectChallenge,
|
|
17
17
|
checkConnectSolution as coreCheckConnectSolution
|
|
18
|
-
} from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs';
|
|
19
|
-
import { createPoolConfigFromJson, KeystonePoolTemplate
|
|
18
|
+
} from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs';
|
|
19
|
+
import { createPoolConfigFromJson, KeystonePoolTemplate } from '@ibgib/core-gib/dist/keystone/keystone-config-builder.mjs';
|
|
20
20
|
import { KeystonePoolConfig } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
|
|
21
21
|
|
|
22
22
|
import rawPolicies from './keystone-policies.json' assert { type: 'json' };
|
|
@@ -25,8 +25,7 @@ import rawPolicies from './keystone-policies.json' assert { type: 'json' };
|
|
|
25
25
|
// 1. JSON Configuration Mapping & Hybrid Fallbacks
|
|
26
26
|
// ---------------------------------------------------------------------------
|
|
27
27
|
|
|
28
|
-
export const
|
|
29
|
-
export const pools = rawPolicies.pools as Record<string, KeystonePoolTemplate>;
|
|
28
|
+
export const pools = rawPolicies.pools as unknown as Record<string, KeystonePoolTemplate>;
|
|
30
29
|
|
|
31
30
|
/**
|
|
32
31
|
* Resolves a pool config by key from the JSON policy file, with fallback behavior.
|
|
@@ -38,7 +37,6 @@ export function getSpaceGibPoolConfig(poolKey: string, salt: string): KeystonePo
|
|
|
38
37
|
}
|
|
39
38
|
return createPoolConfigFromJson({
|
|
40
39
|
template,
|
|
41
|
-
behaviorProfiles,
|
|
42
40
|
salt
|
|
43
41
|
});
|
|
44
42
|
}
|
|
@@ -69,7 +67,7 @@ export const SESSION_KEYSTONE_POLICY = {
|
|
|
69
67
|
* We want more for this, with future implementations we will not have
|
|
70
68
|
* resource exhaustion.
|
|
71
69
|
*/
|
|
72
|
-
|
|
70
|
+
TARGET_BINDING_COUNT: 3,
|
|
73
71
|
},
|
|
74
72
|
|
|
75
73
|
/**
|
|
@@ -1,94 +1,99 @@
|
|
|
1
|
-
import { respecfully, iReckon, ifWe } from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
1
|
+
// import { respecfully, iReckon, ifWe } from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
|
|
2
|
+
// import {
|
|
3
|
+
// isSafePath, isValidStaticPath,
|
|
4
|
+
// // API_PATHS, getPathParams, MAX_PATH_LENGTH,
|
|
5
|
+
// validateAddressSegment
|
|
6
|
+
// } from './path-helper.mjs';
|
|
7
|
+
// import { MAX_PATH_LENGTH } from './path-constants.mts';
|
|
8
|
+
|
|
9
|
+
// const sir = `[${import.meta.url}]`;
|
|
10
|
+
|
|
11
|
+
// await respecfully(sir, 'Path Helper Validation', async () => {
|
|
12
|
+
|
|
13
|
+
// await respecfully(sir, 'isSafePath', async () => {
|
|
14
|
+
// await ifWe(sir, 'valid simple paths', async () => {
|
|
15
|
+
// iReckon(sir, isSafePath('/api/health')).isGonnaBeTrue();
|
|
16
|
+
// iReckon(sir, isSafePath('/index.html')).isGonnaBeTrue();
|
|
17
|
+
// });
|
|
18
|
+
|
|
19
|
+
// await ifWe(sir, 'too long paths', async () => {
|
|
20
|
+
// const longPath = '/'.repeat(MAX_PATH_LENGTH + 1);
|
|
21
|
+
// iReckon(sir, isSafePath(longPath)).isGonnaBeFalse();
|
|
22
|
+
// });
|
|
23
|
+
|
|
24
|
+
// await ifWe(sir, 'directory traversal attempts', async () => {
|
|
25
|
+
// iReckon(sir, isSafePath('/../etc/passwd')).isGonnaBeFalse();
|
|
26
|
+
// iReckon(sir, isSafePath('/api/../../etc/passwd')).isGonnaBeFalse();
|
|
27
|
+
// });
|
|
28
|
+
|
|
29
|
+
// await ifWe(sir, 'null bytes', async () => {
|
|
30
|
+
// iReckon(sir, isSafePath('/api/health\0')).isGonnaBeFalse();
|
|
31
|
+
// });
|
|
32
|
+
|
|
33
|
+
// await ifWe(sir, 'redundant slashes', async () => {
|
|
34
|
+
// iReckon(sir, isSafePath('/api//health')).isGonnaBeFalse();
|
|
35
|
+
// });
|
|
36
|
+
|
|
37
|
+
// await ifWe(sir, 'dot-file access', async () => {
|
|
38
|
+
// iReckon(sir, isSafePath('/.env')).isGonnaBeFalse();
|
|
39
|
+
// iReckon(sir, isSafePath('/scripts/.hidden')).isGonnaBeFalse();
|
|
40
|
+
// iReckon(sir, isSafePath('/.git/config')).isGonnaBeFalse();
|
|
41
|
+
// });
|
|
42
|
+
// });
|
|
43
|
+
|
|
44
|
+
// await respecfully(sir, 'validateAddressSegment', async () => {
|
|
45
|
+
// await ifWe(sir, 'valid encoded addresses', async () => {
|
|
46
|
+
// const validGib = 'a'.repeat(64);
|
|
47
|
+
// iReckon(sir, validateAddressSegment(`someib%5E${validGib}`)).isGonnaBeTrue();
|
|
48
|
+
// // gib with dots (common in sha256.sha256)
|
|
49
|
+
// const dotGib = `${validGib}.${validGib}`;
|
|
50
|
+
// iReckon(sir, validateAddressSegment(`someib%5E${dotGib}`)).isGonnaBeTrue();
|
|
51
|
+
// });
|
|
52
|
+
|
|
53
|
+
// await ifWe(sir, 'invalid encoded addresses', async () => {
|
|
54
|
+
// iReckon(sir, validateAddressSegment('no_delim')).isGonnaBeFalse();
|
|
55
|
+
// iReckon(sir, validateAddressSegment('%5Estarts_with_delim')).isGonnaBeFalse();
|
|
56
|
+
// iReckon(sir, validateAddressSegment('too%5Emany%5Edelims')).isGonnaBeFalse();
|
|
57
|
+
// iReckon(sir, validateAddressSegment('too%5Emany..dots')).isGonnaBeFalse();
|
|
58
|
+
// iReckon(sir, validateAddressSegment('invalid_chars_!%5Eabc')).isGonnaBeFalse();
|
|
59
|
+
// });
|
|
60
|
+
// });
|
|
61
|
+
|
|
62
|
+
// await respecfully(sir, 'API_PATHS Regexes', async () => {
|
|
63
|
+
// await ifWe(sir, 'HEALTH regex', async () => {
|
|
64
|
+
// iReckon(sir, API_PATHS.HEALTH.test('/api/health')).isGonnaBeTrue();
|
|
65
|
+
// iReckon(sir, API_PATHS.HEALTH.test('/api/health/')).isGonnaBeTrue();
|
|
66
|
+
// iReckon(sir, API_PATHS.HEALTH.test('/api/health/more')).isGonnaBeFalse();
|
|
67
|
+
// });
|
|
68
|
+
|
|
69
|
+
// await ifWe(sir, 'IBGIB_ADDR regex', async () => {
|
|
70
|
+
// // valid encoded addr: someib%5Esomegib
|
|
71
|
+
// const addr = '/api/ibgib/someib%5Esomegib';
|
|
72
|
+
// iReckon(sir, API_PATHS.IBGIB_ADDR.test(addr)).isGonnaBeTrue();
|
|
73
|
+
|
|
74
|
+
// const params = getPathParams(addr, API_PATHS.IBGIB_ADDR);
|
|
75
|
+
// iReckon(sir, params?.[0]).isGonnaBe('someib%5Esomegib');
|
|
76
|
+
// });
|
|
77
|
+
|
|
78
|
+
// await ifWe(sir, 'IBGIB_GRAPH regex', async () => {
|
|
79
|
+
// const path = '/api/ibgib/graph/someib%5Esomegib';
|
|
80
|
+
// iReckon(sir, API_PATHS.IBGIB_GRAPH.test(path)).isGonnaBeTrue();
|
|
81
|
+
|
|
82
|
+
// const params = getPathParams(path, API_PATHS.IBGIB_GRAPH);
|
|
83
|
+
// iReckon(sir, params?.[0]).isGonnaBe('someib%5Esomegib');
|
|
84
|
+
// });
|
|
85
|
+
|
|
86
|
+
// await ifWe(sir, 'KEYSTONE regex', async () => {
|
|
87
|
+
// iReckon(sir, API_PATHS.KEYSTONE.test('/api/keystone')).isGonnaBeTrue();
|
|
88
|
+
// iReckon(sir, API_PATHS.KEYSTONE.test('/api/keystone/')).isGonnaBeTrue();
|
|
89
|
+
// });
|
|
90
|
+
|
|
91
|
+
// await ifWe(sir, 'KEYSTONE_EVOLVE regex', async () => {
|
|
92
|
+
// const path = '/api/keystone/evolve/someib%5Esomegib';
|
|
93
|
+
// iReckon(sir, API_PATHS.KEYSTONE_EVOLVE.test(path)).isGonnaBeTrue();
|
|
94
|
+
|
|
95
|
+
// const params = getPathParams(path, API_PATHS.KEYSTONE_EVOLVE);
|
|
96
|
+
// iReckon(sir, params?.[0]).isGonnaBe('someib%5Esomegib');
|
|
97
|
+
// });
|
|
98
|
+
// });
|
|
99
|
+
// });
|
|
@@ -32,3 +32,12 @@ The `RouteInfo` object provides an enriched view of the incoming request:
|
|
|
32
32
|
The `ServeGib_V1` executes handlers in the order they are provided in the `handlers` array. The first handler to return a non-undefined `ResponseResult` wins.
|
|
33
33
|
* **Tip**: Order specific routes (like `/api/ibgib/graph`) before more general ones (like `/api/ibgib`).
|
|
34
34
|
* **Fallback**: The `ErrorHandler` is used as a final catch-all for 404s and fatal errors.
|
|
35
|
+
|
|
36
|
+
## Docker / Server Resilience Note
|
|
37
|
+
When deploying or running this service (or any downstream applications) within a Docker Compose environment, ensure that the `docker-compose.yml` configuration specifies a restart policy such as:
|
|
38
|
+
```yaml
|
|
39
|
+
services:
|
|
40
|
+
space-gib:
|
|
41
|
+
restart: unless-stopped
|
|
42
|
+
```
|
|
43
|
+
This ensures that the container auto-recovers and restarts if the node process crashes due to unhandled events (such as raw TCP socket `ECONNRESET` exceptions from client refreshes).
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
14
14
|
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
|
|
15
15
|
import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
|
|
16
|
-
import { validateAndRegisterEvolveKeystone } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs';
|
|
16
|
+
import { validateAndRegisterEvolveKeystone } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs';
|
|
17
17
|
import { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
|
|
18
18
|
|
|
19
19
|
import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
|
|
@@ -133,7 +133,7 @@ export class KeystoneGenesisHandler extends ServeGibHandlerBase<undefined, undef
|
|
|
133
133
|
await metaspace.registerNewIbGib({ ibGib: keystoneIbGib, space });
|
|
134
134
|
|
|
135
135
|
console.log(`${lc} domain created and keystone persisted: ${addr}`);
|
|
136
|
-
if (logalot) { console.log(`${lc} keystoneIbGib: ${pretty(keystoneIbGib)} (I: d598c6ff7a48997d585b84c19c464826)`); }
|
|
136
|
+
// if (logalot) { console.log(`${lc} keystoneIbGib: ${pretty(keystoneIbGib)} (I: d598c6ff7a48997d585b84c19c464826)`); }
|
|
137
137
|
return this.ok({ success: true, addr }, 201);
|
|
138
138
|
} catch (error) {
|
|
139
139
|
const emsg = extractErrorMsg(error);
|
|
@@ -38,7 +38,7 @@ await respecfully(sir, 'Keystone GET Integration', async () => {
|
|
|
38
38
|
}
|
|
39
39
|
mkdirSync(testDataDir, { recursive: true });
|
|
40
40
|
|
|
41
|
-
await
|
|
41
|
+
await ifWe(sir, 'retrieve a keystone chain via GET /api/keystone/:addr', async () => {
|
|
42
42
|
const keystoneService = new KeystoneService_V1();
|
|
43
43
|
const config = createStandardPoolConfig({ id: POOL_ID_DEFAULT, salt: POOL_ID_DEFAULT });
|
|
44
44
|
|
|
@@ -67,8 +67,8 @@ await respecfully(sir, 'Keystone GET Integration', async () => {
|
|
|
67
67
|
method: 'POST',
|
|
68
68
|
headers: { 'ibgib-domain': addr, 'content-type': 'application/json' },
|
|
69
69
|
on: (event: string, cb: any) => {
|
|
70
|
-
if (event === 'data') cb(Buffer.from(JSON.stringify({ ibGibs: [genesis] })));
|
|
71
|
-
if (event === 'end') cb();
|
|
70
|
+
if (event === 'data') { cb(Buffer.from(JSON.stringify({ ibGibs: [genesis] }))); }
|
|
71
|
+
if (event === 'end') { cb(); }
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
74
|
const postRes: any = {
|
|
@@ -83,7 +83,7 @@ await respecfully(sir, 'Keystone GET Integration', async () => {
|
|
|
83
83
|
method: 'GET',
|
|
84
84
|
headers: { 'ibgib-domain': addr },
|
|
85
85
|
on: (event: string, cb: any) => {
|
|
86
|
-
if (event === 'end') cb();
|
|
86
|
+
if (event === 'end') { cb(); }
|
|
87
87
|
}
|
|
88
88
|
};
|
|
89
89
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
6
|
-
import { validateAndRegisterPostKeystones } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs';
|
|
6
|
+
import { validateAndRegisterPostKeystones } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs';
|
|
7
7
|
|
|
8
8
|
import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
|
|
9
9
|
import { ServeGibHandlerBase } from '../../handler-base.mjs';
|
|
@@ -11,8 +11,8 @@ import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs
|
|
|
11
11
|
import { getIbGibAddr, getIbAndGib } from '@ibgib/ts-gib/dist/helper.mjs';
|
|
12
12
|
import { validateIbGibAddr } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';
|
|
13
13
|
import { parseKeystoneIb } from '@ibgib/core-gib/dist/keystone/keystone-helpers.mjs';
|
|
14
|
-
import { SyncPeerWebSocketReceiver_V1, IWebSocketWrapper } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs';
|
|
15
|
-
import { validateUpfrontConnect } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs';
|
|
14
|
+
import { SyncPeerWebSocketReceiver_V1, IWebSocketWrapper } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs';
|
|
15
|
+
import { validateUpfrontConnect } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs';
|
|
16
16
|
import { SyncSagaCoordinator } from '@ibgib/core-gib/dist/sync/sync-saga-coordinator.mjs';
|
|
17
17
|
|
|
18
18
|
import { GLOBAL_LOG_A_LOT } from '../../constants.mjs';
|
|
@@ -94,10 +94,26 @@ export abstract class SyncUpgradeHandlerBase extends ServeGibHandlerWithMetaspac
|
|
|
94
94
|
sagaId: undefined, // Resolved dynamically inside runtime turns
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
+
// Handle raw socket errors to prevent unhandled 'error' crash (e.g. ECONNRESET)
|
|
98
|
+
socket.on('error', (err) => {
|
|
99
|
+
if (logalot) { console.warn(`[SyncUpgradeHandlerBase] Socket error: ${extractErrorMsg(err)}`); }
|
|
100
|
+
try {
|
|
101
|
+
socket.destroy();
|
|
102
|
+
} catch (e) {
|
|
103
|
+
// ignore
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
97
107
|
// 6. Map standard Node.js Socket to platform-agnostic IWebSocketWrapper
|
|
98
108
|
const socketWrapper: IWebSocketWrapper = {
|
|
99
109
|
send(data: string): void {
|
|
100
|
-
socket.
|
|
110
|
+
if (socket.writable) {
|
|
111
|
+
try {
|
|
112
|
+
socket.write(encodeTextFrame(data));
|
|
113
|
+
} catch (e) {
|
|
114
|
+
if (logalot) { console.warn(`[SyncUpgradeHandlerBase] failed to write message frame: ${extractErrorMsg(e)}`); }
|
|
115
|
+
}
|
|
116
|
+
}
|
|
101
117
|
},
|
|
102
118
|
onMessage(callback: (data: string) => void): void {
|
|
103
119
|
const decoder = new WebSocketFrameDecoder();
|
|
@@ -111,13 +127,29 @@ export abstract class SyncUpgradeHandlerBase extends ServeGibHandlerWithMetaspac
|
|
|
111
127
|
}
|
|
112
128
|
} catch (error) {
|
|
113
129
|
if (logalot) { console.warn(`[SyncUpgradeHandlerBase] closing connection due to decoder error: ${extractErrorMsg(error)}`); }
|
|
114
|
-
socket.
|
|
130
|
+
if (socket.writable) {
|
|
131
|
+
try {
|
|
132
|
+
socket.write(encodeCloseFrame());
|
|
133
|
+
} catch (e) {
|
|
134
|
+
// ignore
|
|
135
|
+
}
|
|
136
|
+
}
|
|
115
137
|
socket.end();
|
|
116
138
|
}
|
|
117
139
|
});
|
|
118
140
|
},
|
|
119
141
|
onClose(callback: () => void): void {
|
|
120
142
|
socket.on('close', callback);
|
|
143
|
+
},
|
|
144
|
+
close(): void {
|
|
145
|
+
if (socket.writable) {
|
|
146
|
+
try {
|
|
147
|
+
socket.write(encodeCloseFrame());
|
|
148
|
+
} catch (e) {
|
|
149
|
+
// ignore
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
socket.end();
|
|
121
153
|
}
|
|
122
154
|
};
|
|
123
155
|
|
|
@@ -134,7 +166,7 @@ export abstract class SyncUpgradeHandlerBase extends ServeGibHandlerWithMetaspac
|
|
|
134
166
|
|
|
135
167
|
protected override async parseParamsImpl(reqCtx: RequestContext<ParamsWithDomain>): Promise<ParamsWithDomain | undefined> {
|
|
136
168
|
const match = reqCtx.pathname.match(this.regex);
|
|
137
|
-
if (!match) return undefined;
|
|
169
|
+
if (!match) { return undefined; }
|
|
138
170
|
const domainIb = decodeURIComponent(match[1]);
|
|
139
171
|
const domainGib = decodeURIComponent(match[2]);
|
|
140
172
|
const domainAddr = getIbGibAddr({ ib: domainIb, gib: domainGib });
|