gdc-common-utils-ts 1.13.0 → 1.14.0
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/README.md +11 -0
- package/dist/constants/dataspace-discovery.d.ts +11 -0
- package/dist/constants/dataspace-discovery.js +11 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.js +1 -0
- package/dist/examples/shared.d.ts +4 -0
- package/dist/examples/shared.js +6 -2
- package/dist/models/dataspace-discovery-defaults.d.ts +78 -0
- package/dist/models/dataspace-discovery-defaults.js +2 -0
- package/dist/models/index.d.ts +1 -0
- package/dist/models/index.js +1 -0
- package/dist/utils/dataspace-discovery-defaults.d.ts +66 -0
- package/dist/utils/dataspace-discovery-defaults.js +172 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -89,6 +89,9 @@ import { JweObject, JwtCompactParts } from 'gdc-common-utils-ts/models';
|
|
|
89
89
|
- [docs/DATASPACE_DISCOVERY_ROADMAP.md](docs/DATASPACE_DISCOVERY_ROADMAP.md)
|
|
90
90
|
- cross-repo contract for dataspace discovery semantics, EU coverage
|
|
91
91
|
inference, shared DTOs, and parameterized examples
|
|
92
|
+
- [docs/DATASPACE_DISCOVERY_DEFAULTS_101.md](docs/DATASPACE_DISCOVERY_DEFAULTS_101.md)
|
|
93
|
+
- portal/backend bootstrap guide for `defaults-only`, `default-first`, and
|
|
94
|
+
`internet-first` discovery seeding by `jurisdiction + version + networkType`
|
|
92
95
|
- [docs/consent-access-matrix-task.md](docs/consent-access-matrix-task.md)
|
|
93
96
|
- next-step design/task document for active consent aggregation, explicit deny precedence, controller views, permission-request communications, and SMART access evaluation
|
|
94
97
|
|
|
@@ -105,9 +108,17 @@ Main entry points:
|
|
|
105
108
|
- [`src/utils/dataspace-discovery.ts`](src/utils/dataspace-discovery.ts)
|
|
106
109
|
- semantic extraction, provider filtering, default DTO builders, and the
|
|
107
110
|
copy/paste fetcher harness used by docs/tests
|
|
111
|
+
- [`src/utils/dataspace-discovery-defaults.ts`](src/utils/dataspace-discovery-defaults.ts)
|
|
112
|
+
- defaults registry for ICAs and hosting operators plus the backend
|
|
113
|
+
`default-first` bootstrap plan used to unblock portal integration
|
|
108
114
|
- [`src/examples/dataspace-discovery.ts`](src/examples/dataspace-discovery.ts)
|
|
109
115
|
- synthetic provider/operator examples that distinguish discovery URL from
|
|
110
116
|
derived catalog artifact URL
|
|
117
|
+
- [`docs/DATASPACE_DISCOVERY_DEFAULTS_101.md`](docs/DATASPACE_DISCOVERY_DEFAULTS_101.md)
|
|
118
|
+
- copy/paste backend bootstrap guide for portal `default-first` rollout
|
|
119
|
+
- [`__tests__/dataspace-discovery-defaults.101.test.ts`](__tests__/dataspace-discovery-defaults.101.test.ts)
|
|
120
|
+
- executable defaults-registry examples for ICAs, hosting operators, and
|
|
121
|
+
source-mode behavior
|
|
111
122
|
- [`__tests__/dataspace-protocol.test.ts`](__tests__/dataspace-protocol.test.ts)
|
|
112
123
|
- executable path and `dspace-version` examples
|
|
113
124
|
- [`__tests__/dataspace-discovery.test.ts`](__tests__/dataspace-discovery.test.ts)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared discovery-source policies used by backend/bootstrap layers that must
|
|
3
|
+
* decide whether to start from configured defaults or from live internet/ICA
|
|
4
|
+
* discovery.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DataspaceDiscoverySourceMode: Readonly<{
|
|
7
|
+
readonly DefaultFirst: "default-first";
|
|
8
|
+
readonly DefaultsOnly: "defaults-only";
|
|
9
|
+
readonly InternetFirst: "internet-first";
|
|
10
|
+
}>;
|
|
11
|
+
export type DataspaceDiscoverySourceModeValue = typeof DataspaceDiscoverySourceMode[keyof typeof DataspaceDiscoverySourceMode];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
/**
|
|
3
|
+
* Shared discovery-source policies used by backend/bootstrap layers that must
|
|
4
|
+
* decide whether to start from configured defaults or from live internet/ICA
|
|
5
|
+
* discovery.
|
|
6
|
+
*/
|
|
7
|
+
export const DataspaceDiscoverySourceMode = Object.freeze({
|
|
8
|
+
DefaultFirst: 'default-first',
|
|
9
|
+
DefaultsOnly: 'defaults-only',
|
|
10
|
+
InternetFirst: 'internet-first',
|
|
11
|
+
});
|
package/dist/constants/index.js
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export declare const EXAMPLE_TENANT_IDENTIFIER: "acme-id";
|
|
12
12
|
export declare const EXAMPLE_JURISDICTION: "ES";
|
|
13
|
+
export declare const EXAMPLE_NETWORK_TYPE: "test";
|
|
14
|
+
export declare const EXAMPLE_ROUTE_VERSION: "v1";
|
|
13
15
|
export declare const EXAMPLE_SECTOR: "health-care";
|
|
14
16
|
export declare const EXAMPLE_EMAIL_CONTROLLER_ORG: "controller@acme.org";
|
|
15
17
|
export declare const EXAMPLE_EMAIL_CONTROLLER_INDIVIDUAL: "ana.parent@example.org";
|
|
@@ -33,6 +35,8 @@ export declare const EXAMPLE_PROVIDER_ORGANIZATION_DID: "did:web:hospital.acme.o
|
|
|
33
35
|
export declare const EXAMPLE_PROVIDER_ORGANIZATION_URL: "https://hospital.acme.org";
|
|
34
36
|
export declare const EXAMPLE_GATEWAY_PUBLIC_ORIGIN: "https://gateway.example.com";
|
|
35
37
|
export declare const EXAMPLE_HOST_PUBLIC_HOSTNAME: "host.example.com";
|
|
38
|
+
export declare const EXAMPLE_DEFAULT_ICA_URL: "https://ica.example.org";
|
|
39
|
+
export declare const EXAMPLE_DEFAULT_ICA_DID: "did:web:ica.example.org";
|
|
36
40
|
export declare const EXAMPLE_HOSTING_OPERATOR_DID: "did:web:host.example.org";
|
|
37
41
|
export declare const EXAMPLE_TENANT_SERVICE_DID: "did:web:provider.example.org";
|
|
38
42
|
export declare const EXAMPLE_SECONDARY_TENANT_SERVICE_DID: "did:web:provider-b.example.org";
|
package/dist/examples/shared.js
CHANGED
|
@@ -16,6 +16,8 @@ import { CommunicationClaim } from '../models/interoperable-claims/communication
|
|
|
16
16
|
*/
|
|
17
17
|
export const EXAMPLE_TENANT_IDENTIFIER = 'acme-id';
|
|
18
18
|
export const EXAMPLE_JURISDICTION = 'ES';
|
|
19
|
+
export const EXAMPLE_NETWORK_TYPE = HostNetworkTypes.Test;
|
|
20
|
+
export const EXAMPLE_ROUTE_VERSION = 'v1';
|
|
19
21
|
export const EXAMPLE_SECTOR = DataspaceSectors.HealthCare;
|
|
20
22
|
export const EXAMPLE_EMAIL_CONTROLLER_ORG = 'controller@acme.org';
|
|
21
23
|
export const EXAMPLE_EMAIL_CONTROLLER_INDIVIDUAL = 'ana.parent@example.org';
|
|
@@ -39,11 +41,13 @@ export const EXAMPLE_PROVIDER_ORGANIZATION_DID = 'did:web:hospital.acme.org';
|
|
|
39
41
|
export const EXAMPLE_PROVIDER_ORGANIZATION_URL = 'https://hospital.acme.org';
|
|
40
42
|
export const EXAMPLE_GATEWAY_PUBLIC_ORIGIN = 'https://gateway.example.com';
|
|
41
43
|
export const EXAMPLE_HOST_PUBLIC_HOSTNAME = 'host.example.com';
|
|
44
|
+
export const EXAMPLE_DEFAULT_ICA_URL = 'https://ica.example.org';
|
|
45
|
+
export const EXAMPLE_DEFAULT_ICA_DID = 'did:web:ica.example.org';
|
|
42
46
|
export const EXAMPLE_HOSTING_OPERATOR_DID = 'did:web:host.example.org';
|
|
43
47
|
export const EXAMPLE_TENANT_SERVICE_DID = 'did:web:provider.example.org';
|
|
44
48
|
export const EXAMPLE_SECONDARY_TENANT_SERVICE_DID = 'did:web:provider-b.example.org';
|
|
45
|
-
export const EXAMPLE_HOSTING_OPERATOR_DSPACE_VERSION_URL = `https://host.example.org/host/cds-ES
|
|
46
|
-
export const EXAMPLE_HOSTING_OPERATOR_CATALOG_ARTIFACT_URL = `https://host.example.org/host/cds-ES
|
|
49
|
+
export const EXAMPLE_HOSTING_OPERATOR_DSPACE_VERSION_URL = `https://host.example.org/host/cds-ES/${EXAMPLE_ROUTE_VERSION}/${EXAMPLE_NETWORK_TYPE}/.well-known/dspace-version`;
|
|
50
|
+
export const EXAMPLE_HOSTING_OPERATOR_CATALOG_ARTIFACT_URL = `https://host.example.org/host/cds-ES/${EXAMPLE_ROUTE_VERSION}/${EXAMPLE_NETWORK_TYPE}/dsp/catalog/dcat.json`;
|
|
47
51
|
/** @deprecated Use `EXAMPLE_HOSTING_OPERATOR_DSPACE_VERSION_URL`. */
|
|
48
52
|
export const EXAMPLE_HOSTING_OPERATOR_CATALOG_URL = EXAMPLE_HOSTING_OPERATOR_DSPACE_VERSION_URL;
|
|
49
53
|
export const EXAMPLE_PROVIDER_PUBLISHED_ENDPOINT_URL = 'https://host.example.org/catalog/provider-a';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { DataspaceDiscoverySourceModeValue } from '../constants/dataspace-discovery';
|
|
2
|
+
import type { HostingOperatorSemanticRecord } from './dataspace-discovery';
|
|
3
|
+
/**
|
|
4
|
+
* Shared host/ICA context used to select dataspace discovery defaults.
|
|
5
|
+
*
|
|
6
|
+
* `networkType` belongs to the host/ICA side.
|
|
7
|
+
* Tenant/provider resolution later uses `sector`.
|
|
8
|
+
*/
|
|
9
|
+
export type DataspaceDiscoveryNetworkContext = Readonly<{
|
|
10
|
+
jurisdiction: string;
|
|
11
|
+
version: string;
|
|
12
|
+
networkType: string;
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* Configured ICA seed for a given host/network context.
|
|
16
|
+
*/
|
|
17
|
+
export type DefaultIcaRegistration = DataspaceDiscoveryNetworkContext & Readonly<{
|
|
18
|
+
icaUrl: string;
|
|
19
|
+
icaDid?: string;
|
|
20
|
+
title?: string;
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* Configured hosting-operator seed for a given host/network context.
|
|
24
|
+
*
|
|
25
|
+
* This mirrors the record shape consumed later by backend resolvers.
|
|
26
|
+
*/
|
|
27
|
+
export type DefaultHostingOperatorRegistration = DataspaceDiscoveryNetworkContext & Readonly<{
|
|
28
|
+
operatorDid: string;
|
|
29
|
+
discoveryUrl?: string;
|
|
30
|
+
catalogUrl?: string;
|
|
31
|
+
record: HostingOperatorSemanticRecord;
|
|
32
|
+
title?: string;
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* Optional seed data used when constructing a defaults registry.
|
|
36
|
+
*/
|
|
37
|
+
export type DataspaceDiscoveryDefaultsRegistrySeed = Readonly<{
|
|
38
|
+
icas?: readonly DefaultIcaRegistration[];
|
|
39
|
+
hostingOperators?: readonly DefaultHostingOperatorRegistration[];
|
|
40
|
+
}>;
|
|
41
|
+
/**
|
|
42
|
+
* Filter used to list configured ICA defaults for a host/network context.
|
|
43
|
+
*/
|
|
44
|
+
export type DataspaceDiscoveryDefaultIcaFilter = Readonly<Partial<DataspaceDiscoveryNetworkContext>>;
|
|
45
|
+
/**
|
|
46
|
+
* Filter used to list configured hosting-operator defaults for a discovery
|
|
47
|
+
* request.
|
|
48
|
+
*/
|
|
49
|
+
export type DataspaceDiscoveryDefaultHostingFilter = Readonly<Partial<DataspaceDiscoveryNetworkContext> & {
|
|
50
|
+
sector?: string;
|
|
51
|
+
coverageScope?: string;
|
|
52
|
+
requiredCapabilities?: readonly string[];
|
|
53
|
+
}>;
|
|
54
|
+
/**
|
|
55
|
+
* Input used to decide how a backend should bootstrap discovery for a
|
|
56
|
+
* frontend/API request.
|
|
57
|
+
*/
|
|
58
|
+
export type DataspaceDiscoveryBootstrapInput = DataspaceDiscoveryNetworkContext & Readonly<{
|
|
59
|
+
sector: string;
|
|
60
|
+
coverageScope?: string;
|
|
61
|
+
requiredCapabilities?: readonly string[];
|
|
62
|
+
sourceMode?: DataspaceDiscoverySourceModeValue;
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Bootstrap plan returned by the defaults registry.
|
|
66
|
+
*
|
|
67
|
+
* Backend usage:
|
|
68
|
+
* - use `hostingOperators` immediately when `shouldUseDefaultsFirst` is true
|
|
69
|
+
* - try live ICA/internet only when `shouldTryInternet` is true
|
|
70
|
+
*/
|
|
71
|
+
export type DataspaceDiscoveryBootstrapPlan = Readonly<{
|
|
72
|
+
sourceMode: DataspaceDiscoverySourceModeValue;
|
|
73
|
+
icas: DefaultIcaRegistration[];
|
|
74
|
+
hostingOperators: DefaultHostingOperatorRegistration[];
|
|
75
|
+
hasDefaults: boolean;
|
|
76
|
+
shouldUseDefaultsFirst: boolean;
|
|
77
|
+
shouldTryInternet: boolean;
|
|
78
|
+
}>;
|
package/dist/models/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * from './consent-rule';
|
|
|
13
13
|
export * from './consent-access';
|
|
14
14
|
export * from './crypto';
|
|
15
15
|
export * from './dataspace-discovery';
|
|
16
|
+
export * from './dataspace-discovery-defaults';
|
|
16
17
|
export * from './dataspace-protocol';
|
|
17
18
|
export * from './device-license';
|
|
18
19
|
export * from './did';
|
package/dist/models/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export * from './consent-rule.js';
|
|
|
13
13
|
export * from './consent-access.js';
|
|
14
14
|
export * from './crypto.js';
|
|
15
15
|
export * from './dataspace-discovery.js';
|
|
16
|
+
export * from './dataspace-discovery-defaults.js';
|
|
16
17
|
export * from './dataspace-protocol.js';
|
|
17
18
|
export * from './device-license.js';
|
|
18
19
|
export * from './did.js';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { DataspaceDiscoveryBootstrapInput, DataspaceDiscoveryBootstrapPlan, DataspaceDiscoveryDefaultHostingFilter, DataspaceDiscoveryDefaultIcaFilter, DataspaceDiscoveryDefaultsRegistrySeed, DefaultHostingOperatorRegistration, DefaultIcaRegistration } from '../models/dataspace-discovery-defaults';
|
|
2
|
+
/**
|
|
3
|
+
* Mutable in-memory registry for discovery defaults used by portal/backend
|
|
4
|
+
* bootstrap code.
|
|
5
|
+
*
|
|
6
|
+
* Scope:
|
|
7
|
+
* - ICA defaults are indexed by `jurisdiction + version + networkType`
|
|
8
|
+
* - hosting defaults are indexed by `jurisdiction + version + networkType`
|
|
9
|
+
* - sector filtering is applied only when listing hosting operators, because
|
|
10
|
+
* sectors belong to tenant/provider discovery rather than to the host network
|
|
11
|
+
*
|
|
12
|
+
* This registry is intentionally simple and synchronous so backend code can
|
|
13
|
+
* preload defaults during startup and immediately serve the frontend in
|
|
14
|
+
* `defaults-only` or `default-first` mode.
|
|
15
|
+
*/
|
|
16
|
+
export declare class DataspaceDiscoveryDefaultsRegistry {
|
|
17
|
+
private readonly icas;
|
|
18
|
+
private readonly hostingOperators;
|
|
19
|
+
constructor(seed?: DataspaceDiscoveryDefaultsRegistrySeed);
|
|
20
|
+
/**
|
|
21
|
+
* Adds one ICA default for a concrete host/network context.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* registry.addIca({
|
|
26
|
+
* jurisdiction: 'ES',
|
|
27
|
+
* version: 'v1',
|
|
28
|
+
* networkType: 'test',
|
|
29
|
+
* icaUrl: 'https://ica.example.org',
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
addIca(input: DefaultIcaRegistration): this;
|
|
34
|
+
/**
|
|
35
|
+
* Adds one hosting-operator default for a concrete host/network context.
|
|
36
|
+
*
|
|
37
|
+
* The record itself may later serve multiple sectors depending on the
|
|
38
|
+
* semantic categories and capabilities published in `record`.
|
|
39
|
+
*/
|
|
40
|
+
addHostingOperator(input: DefaultHostingOperatorRegistration): this;
|
|
41
|
+
/**
|
|
42
|
+
* Lists configured ICA defaults for a host/network context.
|
|
43
|
+
*/
|
|
44
|
+
listIcas(filter?: DataspaceDiscoveryDefaultIcaFilter): DefaultIcaRegistration[];
|
|
45
|
+
/**
|
|
46
|
+
* Lists configured hosting-operator defaults for a frontend/backend discovery
|
|
47
|
+
* request.
|
|
48
|
+
*
|
|
49
|
+
* Sector and capability filtering are applied against the semantic host
|
|
50
|
+
* record because those dimensions belong to the provider/tenant side.
|
|
51
|
+
*/
|
|
52
|
+
listHostingOperators(filter?: DataspaceDiscoveryDefaultHostingFilter): DefaultHostingOperatorRegistration[];
|
|
53
|
+
/**
|
|
54
|
+
* Builds the backend bootstrap plan for one provider-discovery request.
|
|
55
|
+
*
|
|
56
|
+
* Current default-first policy:
|
|
57
|
+
* - use configured hosting defaults immediately when they exist
|
|
58
|
+
* - only try live ICA/internet when no host defaults match the request and at
|
|
59
|
+
* least one ICA default is configured for the same host/network context
|
|
60
|
+
*/
|
|
61
|
+
buildBootstrapPlan(input: DataspaceDiscoveryBootstrapInput): DataspaceDiscoveryBootstrapPlan;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Convenience factory for the in-memory defaults registry.
|
|
65
|
+
*/
|
|
66
|
+
export declare function createDataspaceDiscoveryDefaultsRegistry(seed?: DataspaceDiscoveryDefaultsRegistrySeed): DataspaceDiscoveryDefaultsRegistry;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
import { DataspaceDiscoverySourceMode, } from '../constants/dataspace-discovery.js';
|
|
3
|
+
import { matchesHostingOperatorDiscoveryFilter } from './dataspace-discovery.js';
|
|
4
|
+
function normalizeString(value) {
|
|
5
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
6
|
+
}
|
|
7
|
+
function normalizeCapabilities(values) {
|
|
8
|
+
return Array.from(new Set((values || []).map((value) => normalizeString(value)).filter(Boolean)));
|
|
9
|
+
}
|
|
10
|
+
function normalizeIcaRegistration(input) {
|
|
11
|
+
return {
|
|
12
|
+
jurisdiction: normalizeString(input.jurisdiction),
|
|
13
|
+
version: normalizeString(input.version),
|
|
14
|
+
networkType: normalizeString(input.networkType),
|
|
15
|
+
icaUrl: normalizeString(input.icaUrl),
|
|
16
|
+
icaDid: normalizeString(input.icaDid) || undefined,
|
|
17
|
+
title: normalizeString(input.title) || undefined,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function normalizeHostingOperatorRegistration(input) {
|
|
21
|
+
return {
|
|
22
|
+
jurisdiction: normalizeString(input.jurisdiction),
|
|
23
|
+
version: normalizeString(input.version),
|
|
24
|
+
networkType: normalizeString(input.networkType),
|
|
25
|
+
operatorDid: normalizeString(input.operatorDid),
|
|
26
|
+
discoveryUrl: normalizeString(input.discoveryUrl) || undefined,
|
|
27
|
+
catalogUrl: normalizeString(input.catalogUrl) || undefined,
|
|
28
|
+
record: {
|
|
29
|
+
...input.record,
|
|
30
|
+
subjectId: normalizeString(input.record.subjectId) || undefined,
|
|
31
|
+
serviceTypes: normalizeCapabilities(input.record.serviceTypes),
|
|
32
|
+
categories: Array.from(new Set((input.record.categories || []).map((value) => normalizeString(value)).filter(Boolean))),
|
|
33
|
+
areaServed: Array.from(new Set((input.record.areaServed || []).map((value) => normalizeString(value)).filter(Boolean))),
|
|
34
|
+
addressCountry: normalizeString(input.record.addressCountry) || undefined,
|
|
35
|
+
coverageScope: normalizeString(input.record.coverageScope) || undefined,
|
|
36
|
+
},
|
|
37
|
+
title: normalizeString(input.title) || undefined,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function matchesNetworkContext(left, right) {
|
|
41
|
+
if (right.jurisdiction && normalizeString(right.jurisdiction) !== left.jurisdiction)
|
|
42
|
+
return false;
|
|
43
|
+
if (right.version && normalizeString(right.version) !== left.version)
|
|
44
|
+
return false;
|
|
45
|
+
if (right.networkType && normalizeString(right.networkType) !== left.networkType)
|
|
46
|
+
return false;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Mutable in-memory registry for discovery defaults used by portal/backend
|
|
51
|
+
* bootstrap code.
|
|
52
|
+
*
|
|
53
|
+
* Scope:
|
|
54
|
+
* - ICA defaults are indexed by `jurisdiction + version + networkType`
|
|
55
|
+
* - hosting defaults are indexed by `jurisdiction + version + networkType`
|
|
56
|
+
* - sector filtering is applied only when listing hosting operators, because
|
|
57
|
+
* sectors belong to tenant/provider discovery rather than to the host network
|
|
58
|
+
*
|
|
59
|
+
* This registry is intentionally simple and synchronous so backend code can
|
|
60
|
+
* preload defaults during startup and immediately serve the frontend in
|
|
61
|
+
* `defaults-only` or `default-first` mode.
|
|
62
|
+
*/
|
|
63
|
+
export class DataspaceDiscoveryDefaultsRegistry {
|
|
64
|
+
icas = [];
|
|
65
|
+
hostingOperators = [];
|
|
66
|
+
constructor(seed = {}) {
|
|
67
|
+
for (const registration of seed.icas || []) {
|
|
68
|
+
this.addIca(registration);
|
|
69
|
+
}
|
|
70
|
+
for (const registration of seed.hostingOperators || []) {
|
|
71
|
+
this.addHostingOperator(registration);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Adds one ICA default for a concrete host/network context.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* registry.addIca({
|
|
80
|
+
* jurisdiction: 'ES',
|
|
81
|
+
* version: 'v1',
|
|
82
|
+
* networkType: 'test',
|
|
83
|
+
* icaUrl: 'https://ica.example.org',
|
|
84
|
+
* });
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
addIca(input) {
|
|
88
|
+
this.icas.push(normalizeIcaRegistration(input));
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Adds one hosting-operator default for a concrete host/network context.
|
|
93
|
+
*
|
|
94
|
+
* The record itself may later serve multiple sectors depending on the
|
|
95
|
+
* semantic categories and capabilities published in `record`.
|
|
96
|
+
*/
|
|
97
|
+
addHostingOperator(input) {
|
|
98
|
+
this.hostingOperators.push(normalizeHostingOperatorRegistration(input));
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Lists configured ICA defaults for a host/network context.
|
|
103
|
+
*/
|
|
104
|
+
listIcas(filter = {}) {
|
|
105
|
+
return this.icas
|
|
106
|
+
.filter((registration) => matchesNetworkContext(registration, filter))
|
|
107
|
+
.map((registration) => ({ ...registration }));
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Lists configured hosting-operator defaults for a frontend/backend discovery
|
|
111
|
+
* request.
|
|
112
|
+
*
|
|
113
|
+
* Sector and capability filtering are applied against the semantic host
|
|
114
|
+
* record because those dimensions belong to the provider/tenant side.
|
|
115
|
+
*/
|
|
116
|
+
listHostingOperators(filter = {}) {
|
|
117
|
+
return this.hostingOperators
|
|
118
|
+
.filter((registration) => matchesNetworkContext(registration, filter))
|
|
119
|
+
.filter((registration) => {
|
|
120
|
+
if (!filter.sector)
|
|
121
|
+
return true;
|
|
122
|
+
return matchesHostingOperatorDiscoveryFilter(registration.record, {
|
|
123
|
+
sector: normalizeString(filter.sector),
|
|
124
|
+
coverageScope: normalizeString(filter.coverageScope) || undefined,
|
|
125
|
+
requiredCapabilities: normalizeCapabilities(filter.requiredCapabilities),
|
|
126
|
+
});
|
|
127
|
+
})
|
|
128
|
+
.map((registration) => ({
|
|
129
|
+
...registration,
|
|
130
|
+
record: {
|
|
131
|
+
...registration.record,
|
|
132
|
+
serviceTypes: [...registration.record.serviceTypes],
|
|
133
|
+
categories: [...registration.record.categories],
|
|
134
|
+
areaServed: [...registration.record.areaServed],
|
|
135
|
+
},
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Builds the backend bootstrap plan for one provider-discovery request.
|
|
140
|
+
*
|
|
141
|
+
* Current default-first policy:
|
|
142
|
+
* - use configured hosting defaults immediately when they exist
|
|
143
|
+
* - only try live ICA/internet when no host defaults match the request and at
|
|
144
|
+
* least one ICA default is configured for the same host/network context
|
|
145
|
+
*/
|
|
146
|
+
buildBootstrapPlan(input) {
|
|
147
|
+
const sourceMode = normalizeString(input.sourceMode)
|
|
148
|
+
|| DataspaceDiscoverySourceMode.DefaultFirst;
|
|
149
|
+
const icas = this.listIcas(input);
|
|
150
|
+
const hostingOperators = this.listHostingOperators(input);
|
|
151
|
+
const hasDefaults = Boolean(icas.length || hostingOperators.length);
|
|
152
|
+
const shouldUseDefaultsFirst = sourceMode !== DataspaceDiscoverySourceMode.InternetFirst;
|
|
153
|
+
const shouldTryInternet = sourceMode !== DataspaceDiscoverySourceMode.DefaultsOnly
|
|
154
|
+
&& icas.length > 0
|
|
155
|
+
&& (sourceMode === DataspaceDiscoverySourceMode.InternetFirst
|
|
156
|
+
|| hostingOperators.length === 0);
|
|
157
|
+
return {
|
|
158
|
+
sourceMode,
|
|
159
|
+
icas,
|
|
160
|
+
hostingOperators,
|
|
161
|
+
hasDefaults,
|
|
162
|
+
shouldUseDefaultsFirst,
|
|
163
|
+
shouldTryInternet,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Convenience factory for the in-memory defaults registry.
|
|
169
|
+
*/
|
|
170
|
+
export function createDataspaceDiscoveryDefaultsRegistry(seed = {}) {
|
|
171
|
+
return new DataspaceDiscoveryDefaultsRegistry(seed);
|
|
172
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from './consent';
|
|
|
8
8
|
export * from './did';
|
|
9
9
|
export * from './did-resolution';
|
|
10
10
|
export * from './dataspace-discovery';
|
|
11
|
+
export * from './dataspace-discovery-defaults';
|
|
11
12
|
export * from './dataspace-protocol';
|
|
12
13
|
export * from './didcomm';
|
|
13
14
|
export * from './didcomm-submit';
|
package/dist/utils/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export * from './consent.js';
|
|
|
8
8
|
export * from './did.js';
|
|
9
9
|
export * from './did-resolution.js';
|
|
10
10
|
export * from './dataspace-discovery.js';
|
|
11
|
+
export * from './dataspace-discovery-defaults.js';
|
|
11
12
|
export * from './dataspace-protocol.js';
|
|
12
13
|
export * from './didcomm.js';
|
|
13
14
|
export * from './didcomm-submit.js';
|