@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,198 +0,0 @@
1
- /**
2
- * @module serve-gib/handlers/api/keystone
3
- */
4
-
5
- import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
6
- import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
7
- import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
8
- import { getGibInfo } from '@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs';
9
- import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
10
- import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
11
- import { validateKeystoneGraph } from '@ibgib/core-gib/dist/keystone/keystone-helpers.mjs';
12
- import { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
13
- import { IbGibSpaceResultData, IbGibSpaceResultIbGib, IbGibSpaceResultRel8ns } from '@ibgib/core-gib/dist/witness/space/space-types.mjs';
14
-
15
- import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
16
- import { ServeGibHandlerWithMetaspaceBase } from '../../handler-base.mjs';
17
- import { RequestContext, ResponseResult, ServeGibHttpMethod } from '../../../types.mjs';
18
- import { API_PATH_REGEXES } from '../../../../path-constants.mjs';
19
- import {
20
- DEFAULT_QUERY_PARAMS_GET_KEYSTONE, isKnownQueryParamsKey_KeystoneGet,
21
- KeystoneGetQueryParams, KeystoneParams, KNOWN_QUERY_PARAMS_KEYSTONE_GET
22
- } from './keystone-handler-types.mjs';
23
- import { validateAndCoerceBooleanQueryParam } from '../../../serve-gib-helpers.mjs';
24
-
25
- export interface KeystoneGetResponseBody {
26
- domainGraph: Record<string, KeystoneIbGib_V1>;
27
- }
28
-
29
- const logalot = GLOBAL_LOG_A_LOT;
30
-
31
- /**
32
- * GET /api/keystone/:domainAddr
33
- * GET /api/keystone/:domainAddr&getLatest=true
34
- */
35
- export class KeystoneGetHandler extends ServeGibHandlerWithMetaspaceBase<KeystoneParams, KeystoneGetQueryParams> {
36
- protected override lc: string = `[${KeystoneGetHandler.name}]`;
37
- protected override method: ServeGibHttpMethod = 'GET';
38
- protected override regex = API_PATH_REGEXES.KEYSTONE_ADDR;
39
-
40
- protected override async parseParamsImpl(reqCtx: RequestContext<KeystoneParams, KeystoneGetQueryParams>): Promise<KeystoneParams | undefined> {
41
- const lc = `${this.lc}[${this.parseParamsImpl.name}]`;
42
- try {
43
- if (logalot) { console.log(`${lc} starting...`); }
44
- const match = reqCtx.pathname.match(this.regex);
45
- if (!match) { throw new Error(`(UNEXPECTED) match falsy for regex? at this point, we have passed canHandleRoute, so this should parse correctly. (E: 02c868316604c7c26823380885b79c26)`); }
46
-
47
- const domainIb = decodeURIComponent(match[1]);
48
- const domainGib = decodeURIComponent(match[2]);
49
- const domainAddr = getIbGibAddr({ ib: domainIb, gib: domainGib });
50
- return {
51
- domainInfo: this.getDomainInfo({ domainAddr }),
52
- };
53
- } catch (error) {
54
- console.error(`${lc} ${extractErrorMsg(error)}`);
55
- throw error;
56
- } finally {
57
- if (logalot) { console.log(`${lc} complete.`); }
58
- }
59
- }
60
-
61
- protected override async validateQueryParams({ queryParams }: { queryParams: any; }): Promise<string[]> {
62
- const lc = `${this.lc}[${this.validateQueryParams.name}]`;
63
- try {
64
- if (logalot) { console.log(`${lc} starting... (I: f619e8121988498cd8e8928986663826)`); }
65
-
66
- const errors: string[] = [];
67
-
68
- // strict checking
69
- const queryParamsKeys = Object.keys(queryParams);
70
- const invalidKeys: string[] = queryParamsKeys.filter(x => !isKnownQueryParamsKey_KeystoneGet(x));
71
- if (invalidKeys.length > 0) {
72
- throw new Error(`invalid query params keys: ${invalidKeys.join(', ')}. valid query params keys: ${KNOWN_QUERY_PARAMS_KEYSTONE_GET.join(', ')} (E: f9642823b568a1cfe89e0401567ac826)`);
73
- }
74
-
75
- // Enforce that EVERY key must have a validation function mapping
76
- type ValidationFn = () => Promise<void>;
77
- const ValidationFns: Record<KNOWN_QUERY_PARAMS_KEYSTONE_GET, ValidationFn> = {
78
- getLatest: async () => {
79
- validateAndCoerceBooleanQueryParam(queryParams, 'getLatest', errors);
80
- },
81
- getGraph: async () => {
82
- validateAndCoerceBooleanQueryParam(queryParams, 'getGraph', errors);
83
- },
84
- };
85
-
86
- // execute all validation functions
87
- for (const fn of Object.values(ValidationFns)) {
88
- await fn();
89
- }
90
-
91
- return errors;
92
-
93
- } catch (error) {
94
- console.error(`${lc} ${extractErrorMsg(error)}`);
95
- throw error;
96
- } finally {
97
- if (logalot) { console.log(`${lc} complete.`); }
98
- }
99
- }
100
-
101
- protected async handleRouteImpl(reqCtx: RequestContext<KeystoneParams, KeystoneGetQueryParams>): Promise<ResponseResult | undefined> {
102
- const lc = `[${this.handleRouteImpl.name}]`;
103
- try {
104
- if (logalot) { console.log(`${lc} starting...`); }
105
-
106
- const { metaspace } = reqCtx;
107
- if (!metaspace) { throw new Error(`(UNEXPECTED) reqCtx.metaspace falsy? (E: 871a396f7e824989981a1508d0d17826)`); }
108
-
109
- const { domainInfo } = reqCtx.params as KeystoneParams;
110
- if (!domainInfo) { throw new Error(`(UNEXPECTED) reqCtx.params.domainInfo falsy? at this point, we've passed canHandleRoute so this should be truthy (E: 5d3e96d9f8d8f65258d530af0e223826)`); }
111
- const { addr: domainAddr } = domainInfo;
112
-
113
- // if (!domainIb || !domainGib) { return this.error(400, 'Keystone address required'); }
114
- // const addr = `${domainIb}^${domainGib}`;
115
-
116
- if (logalot) { console.log(`${lc} domainAddr: ${domainAddr} (I: ea08786359e85481a89c77d84e8f0826)`); }
117
-
118
- // there are two paths for this: getLatest or not (get exact given addr)
119
- // this should be driven by queryParams
120
-
121
- const queryParams = {
122
- ...DEFAULT_QUERY_PARAMS_GET_KEYSTONE,
123
- ...(reqCtx.queryParams ?? {}),
124
- }
125
-
126
- const { getLatest, getGraph } = queryParams;
127
-
128
- if (!getLatest) { throw new Error(`"getLatest: false" not implemented yet. currently this always returns the graph. (E: befd28156438a0b538cf107872e89b26)`); }
129
- if (!getGraph) { throw new Error(`"getGraph: false" not implemented yet. currently this always returns the graph. (E: 84c8a88fdb28e72d884addb8f43fc826)`); }
130
-
131
- /**
132
- * get the default local user space that corresponds to the current
133
- * keystone domain (which is what the metaspace was initialized
134
- * with).
135
- */
136
- const space = await metaspace.getLocalUserSpace({ lock: false });
137
- if (!space) { throw new Error(`(UNEXPECTED) space falsy? we couldn't get the default local userspace from the metaspace for the addr (${domainAddr}) (E: 934551f1845f94c8320a8a980025c526)`); }
138
-
139
-
140
- // use this code later if we de
141
- let domainAddr_latest: IbGibAddr = domainAddr;
142
- if (getLatest) {
143
- const latestAddr = await metaspace.getLatestAddr({ addr: domainAddr, space });
144
- if (latestAddr) { domainAddr_latest = latestAddr; }
145
- }
146
-
147
-
148
- const domainGraph = await metaspace.getDependencyGraph({
149
- ibGibAddr: domainAddr_latest,
150
- /**
151
- * since domain is a keystone, "live" is not needed because the
152
- * entire graph is composed of stones with no timelines.
153
- */
154
- live: false,
155
- space,
156
- });
157
-
158
- let keystoneIbGib: KeystoneIbGib_V1 = domainGraph[domainAddr_latest] as KeystoneIbGib_V1;
159
- if (!keystoneIbGib) {
160
- const errorMsg_addrInfo = domainAddr_latest === domainAddr ?
161
- `domainAddr: ${domainAddr}` :
162
- `domainAddr: ${domainAddr}, domainAddr_latest: `
163
- return this.error(404, `Keystone not found. ${errorMsg_addrInfo} (E: 0238c85f94889607088220a324db1826)`); /* <<<< returns early */
164
- }
165
-
166
- // go ahead and validate even though we just pulled this (should be
167
- // valid or it shouldn't have been persisted)
168
-
169
- const keystoneValidationErrors = await validateKeystoneGraph({
170
- keystoneIbGib,
171
- getLatest,
172
- invalidIfMoreRecentKeystoneFoundInSpace: getLatest,
173
- space,
174
- });
175
-
176
- if (keystoneValidationErrors.length > 0) {
177
- const errorMsg_addrInfo = domainAddr_latest === domainAddr ?
178
- `domainAddr: ${domainAddr}` :
179
- `domainAddr: ${domainAddr}, domainAddr_latest: `
180
-
181
- return this.error(404, `Keystone invalid for ${errorMsg_addrInfo}. validationErrors: ${keystoneValidationErrors.join('|')}`); /* <<<< returns early */
182
- }
183
-
184
- // valid keystone graph
185
- const responseBody: KeystoneGetResponseBody = {
186
- domainGraph: domainGraph as Record<string, KeystoneIbGib_V1>,
187
- };
188
- return this.ok(responseBody);
189
-
190
- } catch (error) {
191
- const emsg = `${lc} ${extractErrorMsg(error)}`;
192
- console.error(emsg);
193
- return this.error(500, emsg);
194
- } finally {
195
- if (logalot) { console.log(`${lc} complete.`); }
196
- }
197
- }
198
- }
@@ -1,107 +0,0 @@
1
- import { join } from 'node:path';
2
- import { existsSync, rmSync, mkdirSync } from 'node:fs';
3
-
4
- import {
5
- respecfully, iReckon, ifWe, ifWeMight
6
- } from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
7
- const sir = `[${import.meta.url}]`;
8
-
9
- import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
10
- import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
11
- import { createStandardPoolConfig } from '@ibgib/core-gib/dist/keystone/keystone-config-builder.mjs';
12
- import { POOL_ID_DEFAULT } from '@ibgib/core-gib/dist/keystone/keystone-constants.mjs';
13
-
14
- import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
15
- import { ServeGib_V1 } from '../../../serve-gib-v1.mjs';
16
- import { KeystonePostHandler } from './keystone-post.handler.mjs';
17
- import { KeystoneGetHandler } from './keystone-get.handler.mjs';
18
- import { ErrorHandler } from '../../error-handler.mjs';
19
-
20
- const logalot = GLOBAL_LOG_A_LOT;
21
-
22
- class MockMetaspace {
23
- async getLocalUserSpace() { return new MockSpace(); }
24
- async put() { }
25
- async registerNewIbGib() { }
26
- }
27
- class MockSpace {
28
- async witness() { return { data: { success: true } }; }
29
- }
30
-
31
- await respecfully(sir, 'Keystone GET Integration', async () => {
32
- const testDataDir = './test-data-get';
33
- const port = 3003;
34
-
35
- // Clean test data
36
- if (existsSync(testDataDir)) {
37
- rmSync(testDataDir, { recursive: true, force: true });
38
- }
39
- mkdirSync(testDataDir, { recursive: true });
40
-
41
- await ifWe(sir, 'retrieve a keystone chain via GET /api/keystone/:addr', async () => {
42
- const keystoneService = new KeystoneService_V1();
43
- const config = createStandardPoolConfig({ id: POOL_ID_DEFAULT, salt: POOL_ID_DEFAULT });
44
-
45
- // 1. Setup ServeGib_V1 with both POST and GET handlers
46
- const serveGib = new ServeGib_V1({
47
- port,
48
- dataDir: testDataDir,
49
- handlers: [
50
- new KeystonePostHandler(),
51
- new KeystoneGetHandler(),
52
- ],
53
- errorHandler: new ErrorHandler()
54
- });
55
-
56
- // 2. Generate and POST genesis
57
- const genesis = await keystoneService.genesis({
58
- masterSecret: 'AliceSecret',
59
- configs: [config],
60
- metaspace: new MockMetaspace() as any,
61
- space: new MockSpace() as any,
62
- });
63
- const addr = getIbGibAddr({ ibGib: genesis });
64
-
65
- const postReq: any = {
66
- url: '/api/keystone',
67
- method: 'POST',
68
- headers: { 'ibgib-domain': addr, 'content-type': 'application/json' },
69
- on: (event: string, cb: any) => {
70
- if (event === 'data') { cb(Buffer.from(JSON.stringify({ ibGibs: [genesis] }))); }
71
- if (event === 'end') { cb(); }
72
- }
73
- };
74
- const postRes: any = {
75
- writeHead: () => { },
76
- end: () => { },
77
- };
78
- await serveGib.handleRequest(postReq, postRes);
79
-
80
- // 3. Mock GET Request
81
- const getReq: any = {
82
- url: `/api/keystone/${encodeURIComponent(addr)}`,
83
- method: 'GET',
84
- headers: { 'ibgib-domain': addr },
85
- on: (event: string, cb: any) => {
86
- if (event === 'end') { cb(); }
87
- }
88
- };
89
-
90
- let capturedStatus: number = 0;
91
- let capturedBody: any = null;
92
- const getRes: any = {
93
- writeHead: (status: number) => { capturedStatus = status; },
94
- end: (body: string) => { capturedBody = JSON.parse(body); },
95
- };
96
-
97
- // 4. Handle GET
98
- await serveGib.handleRequest(getReq, getRes);
99
-
100
- // 5. Verify
101
- iReckon(sir, capturedStatus).asTo('captured status code').isGonnaBe(200);
102
- iReckon(sir, capturedBody.chain).asTo('captured body chain').isGonnaBeTruthy();
103
- iReckon(sir, Array.isArray(capturedBody.chain)).asTo('chain is array').isGonnaBe(true);
104
- iReckon(sir, capturedBody.chain.length).asTo('chain length').isGonnaBe(1);
105
- iReckon(sir, capturedBody.chain[0].gib).asTo('genesis gib matches').isGonnaBe(genesis.gib);
106
- });
107
- });
@@ -1,29 +0,0 @@
1
- import { DomainInfo } from "../../../types.mjs";
2
-
3
- export interface KeystoneParams {
4
- domainInfo: DomainInfo;
5
- }
6
-
7
- // #region KeystoneGetQueryParams
8
- export const DEFAULT_QUERY_PARAMS_GET_KEYSTONE = {
9
- /**
10
- * If true, will get the latest keystone frame.
11
- */
12
- getLatest: true,
13
- /**
14
- * If true, will get the keystone's entire dependency graph
15
- */
16
- getGraph: true,
17
- };
18
- /**
19
- * @see {@link DEFAULT_QUERY_PARAMS_GET_KEYSTONE} key/values for jsdocs
20
- */
21
- export type KeystoneGetQueryParams = Partial<typeof DEFAULT_QUERY_PARAMS_GET_KEYSTONE>;
22
- export type KNOWN_QUERY_PARAMS_KEYSTONE_GET = keyof KeystoneGetQueryParams;
23
- export const KNOWN_QUERY_PARAMS_KEYSTONE_GET = Object.keys(DEFAULT_QUERY_PARAMS_GET_KEYSTONE) as KNOWN_QUERY_PARAMS_KEYSTONE_GET[];
24
- export function isKnownQueryParamsKey_KeystoneGet(key: any): key is KNOWN_QUERY_PARAMS_KEYSTONE_GET {
25
- return !!key && typeof key === 'string' ?
26
- KNOWN_QUERY_PARAMS_KEYSTONE_GET.includes(key as any) :
27
- false;
28
- }
29
- // #endregion KeystoneGetQueryParams
@@ -1,55 +0,0 @@
1
- /**
2
- * @module serve-gib/handlers/api/keystone
3
- */
4
-
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/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs';
7
-
8
- import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
9
- import { ServeGibHandlerBase } from '../../handler-base.mjs';
10
- import { RequestContext, ResponseResult, ServeGibHttpMethod } from '../../../types.mjs';
11
- import { API_PATH_REGEXES } from '../../../../path-constants.mjs';
12
- import { KeystoneParams } from './keystone-handler-types.mjs';
13
-
14
- const logalot = GLOBAL_LOG_A_LOT || true;
15
-
16
- /**
17
- * POST /api/keystone
18
- */
19
- export class KeystonePostHandler extends ServeGibHandlerBase<KeystoneParams, any> { // todo: keystone post query params if needed?
20
- protected override lc: string = `[${KeystonePostHandler.name}]`;
21
- protected override method: ServeGibHttpMethod = 'POST';
22
- protected override regex = API_PATH_REGEXES.KEYSTONE;
23
-
24
- protected async handleRouteImpl(reqCtx: RequestContext<KeystoneParams, any>): Promise<ResponseResult | undefined> {
25
- const lc = `[${this.handleRouteImpl.name}]`;
26
- try {
27
- if (logalot) { console.log(`${lc} starting... (I: 63bab8214834cb6e383e0fc364ee8826)`); }
28
-
29
- const { metaspace } = reqCtx;
30
- if (!metaspace) { throw new Error(`(UNEXPECTED) reqCtx.metaspace falsy? (E: 3d03027ea7f6f237980e511801255826)`); }
31
-
32
- const { ibGibs } = JSON.parse(reqCtx.body) as { ibGibs: any[] };
33
- if (!Array.isArray(ibGibs)) return this.error(400, 'ibGibs array required');
34
-
35
- const space = await metaspace.getLocalUserSpace({ lock: false });
36
- if (!space) { throw new Error(`No local user space found`); }
37
-
38
- // Delegate all intrinsic validation, keystone-specific checks, registration, and persistence to core-gib
39
- await validateAndRegisterPostKeystones({
40
- ibGibs,
41
- metaspace,
42
- space
43
- });
44
-
45
- return { status: 201, body: { success: true }, isJson: true };
46
-
47
- } catch (error) {
48
- const emsg = `${lc} ${extractErrorMsg(error)}`;
49
- console.error(emsg);
50
- return this.error(500, emsg);
51
- } finally {
52
- if (logalot) { console.log(`${lc} complete.`); }
53
- }
54
- }
55
- }
@@ -1,130 +0,0 @@
1
- import { join } from 'node:path';
2
- import { existsSync, rmSync, mkdirSync, readdirSync } from 'node:fs';
3
-
4
- import {
5
- respecfully, iReckon, ifWe, ifWeMight
6
- } from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
7
- const sir = `[${import.meta.url}]`;
8
-
9
- import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
10
- import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
11
- import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
12
- import { createStandardPoolConfig } from '@ibgib/core-gib/dist/keystone/keystone-config-builder.mjs';
13
- import { POOL_ID_DEFAULT } from '@ibgib/core-gib/dist/keystone/keystone-constants.mjs';
14
-
15
- import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
16
- import { ServeGib_V1 } from '../../../serve-gib-v1.mjs';
17
- import { KeystonePostHandler } from './keystone-post.handler.mjs';
18
- import { ErrorHandler } from '../../error-handler.mjs';
19
- import { getDomainRootPath } from '../../../../bootstrap-helper.mjs';
20
-
21
- const logalot = GLOBAL_LOG_A_LOT;
22
- if (logalot) { console.log(`[test] keystone-post.respec.mts top-level entry`); }
23
-
24
- class MockMetaspace {
25
- async getLocalUserSpace() { return new MockSpace(); }
26
- async put() { }
27
- async registerNewIbGib() { }
28
- }
29
- class MockSpace {
30
- async witness() { return { data: { success: true } }; }
31
- }
32
-
33
- await respecfully(sir, 'Keystone POST Integration', async () => {
34
- const testDataDir = './test-data-post';
35
- const port = 3001;
36
-
37
- // Clean test data
38
- if (existsSync(testDataDir)) {
39
- rmSync(testDataDir, { recursive: true, force: true });
40
- }
41
- mkdirSync(testDataDir, { recursive: true });
42
-
43
- await ifWe(sir, 'bootstrap a new domain via POST /api/keystone', async () => {
44
- const keystoneService = new KeystoneService_V1();
45
- const config = createStandardPoolConfig({ id: POOL_ID_DEFAULT, salt: POOL_ID_DEFAULT });
46
-
47
- // 1. Generate real genesis
48
- const genesis = await keystoneService.genesis({
49
- masterSecret: 'AliceSecret',
50
- configs: [config],
51
- metaspace: new MockMetaspace() as any,
52
- space: new MockSpace() as any,
53
- });
54
- const addr = getIbGibAddr({ ibGib: genesis });
55
-
56
- if (logalot) { console.log(`[test] Generated genesis: ${addr}`); }
57
-
58
- // 2. Setup ServeGib_V1
59
- const serveGib = new ServeGib_V1({
60
- port,
61
- dataDir: testDataDir,
62
- handlers: [new KeystonePostHandler()],
63
- errorHandler: new ErrorHandler()
64
- });
65
-
66
- if (logalot) { console.log(`[test] ServeGib_V1 setup. Posting to /api/keystone...`); }
67
-
68
- // 3. Mock POST Request
69
- const req: any = {
70
- url: '/api/keystone',
71
- method: 'POST',
72
- headers: {
73
- 'ibgib-domain': addr,
74
- 'content-type': 'application/json'
75
- },
76
- on: (event: string, cb: any) => {
77
- if (event === 'data') {
78
- if (logalot) { console.log(`[test] sending data chunk...`); }
79
- cb(Buffer.from(JSON.stringify({ ibGibs: [genesis] })));
80
- }
81
- if (event === 'end') {
82
- if (logalot) { console.log(`[test] end of request.`); }
83
- cb();
84
- }
85
- }
86
- };
87
-
88
- let capturedStatus: number = 0;
89
- let capturedBody: any = null;
90
- const res: any = {
91
- writeHead: (status: number) => {
92
- if (logalot) { console.log(`[test] writeHead: ${status}`); }
93
- capturedStatus = status;
94
- },
95
- end: (body: string) => {
96
- if (logalot) { console.log(`[test] res.end called with body length: ${body?.length}`); }
97
- capturedBody = JSON.parse(body);
98
- },
99
- statusCode: 0
100
- };
101
-
102
- // 4. Handle
103
- if (logalot) { console.log(`[test] Calling handleRequest...`); }
104
- await serveGib.handleRequest(req, res);
105
- if (logalot) { console.log(`[test] handleRequest completed.`); }
106
-
107
- // 5. Verify
108
- iReckon(sir, capturedStatus).asTo('captured status code').isGonnaBe(201);
109
- iReckon(sir, capturedBody.success).asTo(`Handler failed: ${capturedBody.message || 'no message'}`).isGonnaBe(true);
110
-
111
- const domainPath = getDomainRootPath(genesis.gib!, testDataDir);
112
- iReckon(sir, existsSync(domainPath)).asTo('domain path exists').isGonnaBe(true);
113
-
114
- // Verify the ibgib actually exists in the new domain's storage
115
- // With indexed storage, it's in a bucketed subpath: ibgib/default/ibgibs/B1/B2/
116
- const bucket1 = genesis.gib!.substring(0, 3).toUpperCase();
117
- const bucket2 = genesis.gib!.substring(3, 6).toUpperCase();
118
- const bucketPath = join(domainPath, 'ibgib', 'default', 'ibgibs', bucket1, bucket2);
119
-
120
- iReckon(sir, existsSync(bucketPath)).asTo(`Bucket path does not exist: ${bucketPath}`).isGonnaBe(true);
121
-
122
- // We don't know the random filename, but we know it's a .json file in that bucket
123
- try {
124
- const files = readdirSync(bucketPath).filter(f => f.endsWith('.json'));
125
- iReckon(sir, files.length > 0).asTo(`No .json files found in bucket: ${bucketPath}`).isGonnaBe(true);
126
- } catch (error) {
127
- iReckon(sir, true).asTo(`error trying to readdir ${bucketPath}: ${extractErrorMsg(error)}`).isGonnaBe(true);
128
- }
129
- });
130
- });
@@ -1,66 +0,0 @@
1
- import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
2
- import { loadSsoServerConfig } from '@ibgib/web-gib/dist/identity/sso/sso-config-helper.mjs';
3
- import { SsoCustodianService } from '@ibgib/web-gib/dist/identity/sso/sso-custodian-service.mjs';
4
-
5
- import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
6
- import { ServeGibHandlerBase } from '../../handler-base.mjs';
7
- import { API_PATH_REGEXES } from '../../../../path-constants.mjs';
8
- import { RequestContext, ResponseResult, ServeGibHttpMethod } from '../../../types.mjs';
9
-
10
- const logalot = GLOBAL_LOG_A_LOT || true;
11
-
12
- let custodian: SsoCustodianService | undefined;
13
- function getCustodian(): SsoCustodianService {
14
- if (!custodian) {
15
- const config = loadSsoServerConfig();
16
- custodian = new SsoCustodianService(config);
17
- }
18
- return custodian;
19
- }
20
-
21
- /**
22
- * GET /api/identity/sso/config
23
- *
24
- * Retrieves safe public client configurations (client ID, scope, auth URLs) for active OAuth2 providers.
25
- */
26
- export class SsoConfigHandler extends ServeGibHandlerBase<any, any> {
27
- protected override lc: string = `[${SsoConfigHandler.name}]`;
28
- protected override method: ServeGibHttpMethod = 'GET';
29
- protected override regex = API_PATH_REGEXES.IDENTITY_SSO_CONFIG;
30
-
31
- protected override async parseParamsImpl(reqCtx: RequestContext<any, any>): Promise<any> {
32
- return undefined;
33
- }
34
-
35
- protected override async validateQueryParams({ queryParams }: { queryParams: any }): Promise<string[]> {
36
- return [];
37
- }
38
-
39
- /**
40
- * @param reqCtx Context details of the incoming request.
41
- * - Visibility: Public/Private (Contextual request information containing headers).
42
- * - Generator: Server (Constructed dynamically by serve-gib-v1 pipeline).
43
- */
44
- protected async handleRouteImpl(reqCtx: RequestContext<any>): Promise<ResponseResult | undefined> {
45
- const lc = `${this.lc}[${this.handleRouteImpl.name}]`;
46
- try {
47
- if (logalot) { console.log(`${lc} starting...`); }
48
-
49
- const service = getCustodian();
50
- const hostUrl = `${reqCtx.protocol}://${reqCtx.headers.host}`;
51
- const providers = service.getSsoClientConfigs(hostUrl);
52
-
53
- return this.ok({
54
- success: true,
55
- providers
56
- }, 200);
57
-
58
- } catch (error) {
59
- const emsg = extractErrorMsg(error);
60
- console.error(`${lc} Fetching SSO config failed: ${emsg}`);
61
- return this.error(500, `SSO configuration retrieval failed: ${emsg}`);
62
- } finally {
63
- if (logalot) { console.log(`${lc} complete.`); }
64
- }
65
- }
66
- }