gdc-sdk-front-ts 0.1.1

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 ADDED
@@ -0,0 +1,94 @@
1
+ # gdc-sdk-front-ts
2
+
3
+ Target frontend runtime package for the converged GDC SDK family.
4
+
5
+ Key docs:
6
+
7
+ - [CHANGELOG.md](CHANGELOG.md)
8
+ - [SECURITY.md](SECURITY.md)
9
+ - [SDK_INTEGRATION_101.md](SDK_INTEGRATION_101.md)
10
+
11
+ Current status:
12
+
13
+ - package created
14
+ - build/test baseline created
15
+ - migration target from `gdc-sdk-client-ts` declared
16
+ - frontend runtime contract skeleton declared
17
+ - shared core identity/discovery/bootstrap contracts are now available for frontend wiring
18
+
19
+ Why `front` and not `expo`:
20
+
21
+ - the SDK architecture is frontend-agnostic
22
+ - Expo is one runtime, not the product boundary
23
+ - the same package family should later support web portal and Expo/mobile adapters
24
+
25
+ Not migrated yet:
26
+
27
+ - `ClientSDK`
28
+ - `ProfileManager`
29
+ - `roleRegistry`
30
+ - `capabilityMapper`
31
+ - app-facing session bootstrap
32
+ - Expo/web adapter implementations
33
+ - provider/operator/ICA discovery facade wiring
34
+ - explicit device/actor/provider identity store wiring
35
+ - controller bootstrap helper for `_activate` with `vp_token + controller.*`
36
+
37
+ Role in the transition:
38
+
39
+ - `gdc-sdk-core-ts` will own shared actor/capability contracts
40
+ - `gdc-sdk-front-ts` will own frontend-facing runtime adapters and session/profile orchestration
41
+ - `gdc-sdk-client-ts` is now the legacy source repo for migration, not the final name
42
+
43
+ Reusable payload source of truth:
44
+
45
+ - `gdc-common-utils-ts/examples/frontend-session`
46
+ - session/profile bootstrap examples
47
+ - `gdc-common-utils-ts/examples/professional`
48
+ - lightweight communication/search request examples reused by frontend services
49
+ - reusable professional role/permission scenarios by section and expected FHIR types
50
+ - reusable consent-vs-smart matrices for actor targeting by email, organization, or jurisdiction
51
+ - `gdc-common-utils-ts/examples/api-flow-examples`
52
+ - preferred compatibility aggregator when one import surface is needed without using the overloaded term `contract`
53
+
54
+ CORE vs extension note:
55
+
56
+ - CORE shared examples model provider and actor identities with DID/email-first semantics
57
+ - phone-only subject/controller fields are compatibility or product-extension concerns, not required CORE GW inputs
58
+ - individual/family bootstrap uses `org.schema.Organization.owner.*` claims for the owner/controller of the subject index
59
+ - legal organization activation uses `Person` representative semantics plus VC `memberOf` / `hasOccupation`
60
+
61
+ ## API Index
62
+
63
+ The canonical API contract should live in JSDoc on exported code. The README is the linked index.
64
+
65
+ ### Core draft/document helpers re-exported from `gdc-sdk-core-ts`
66
+
67
+ - [`createCommunicationDraft(...)`](../gdc-sdk-core-ts/src/communication-draft.ts)
68
+ - Starts an in-memory communication draft.
69
+ - [`addFhirResourceToDraft(...)`](../gdc-sdk-core-ts/src/communication-draft.ts)
70
+ - Appends a concrete FHIR resource or document.
71
+ - [`addClaimsResourceToDraft(...)`](../gdc-sdk-core-ts/src/communication-draft.ts)
72
+ - Appends a claims-only pseudo-resource.
73
+ - [`createOutboxJobFromDraft(...)`](../gdc-sdk-core-ts/src/communication-draft.ts)
74
+ - Freezes the draft into a transport-oriented outbox job.
75
+ - [`updateOutboxJobStatus(...)`](../gdc-sdk-core-ts/src/communication-draft.ts)
76
+ - Updates the outbox job status in memory.
77
+ - [`IOutboxRepository`](../gdc-sdk-core-ts/src/communication-outbox.ts)
78
+ - [`OutboxRepositoryMemory`](../gdc-sdk-core-ts/src/communication-outbox.ts)
79
+ - [`createCommunicationFacade()`](../gdc-sdk-core-ts/src/communication-document-facade.ts)
80
+ - Resolves documents from FHIR `Communication`.
81
+ - [`createHeartRateObservation(...)`](../gdc-sdk-core-ts/src/vital-signs.ts)
82
+ - [`createBodyTemperatureObservation(...)`](../gdc-sdk-core-ts/src/vital-signs.ts)
83
+ - [`createBloodPressureObservation(...)`](../gdc-sdk-core-ts/src/vital-signs.ts)
84
+
85
+ ### Runtime configuration
86
+
87
+ - [`FrontRuntimeConfig`](src/runtime-contracts.ts)
88
+ - Includes `persistencePolicy?` and `outboxRepositoryFactory?` so frontend runtimes can disable local persistence on shared devices or use secure local storage on confidential devices.
89
+
90
+ ### Documentation rule
91
+
92
+ - JSDoc on exported code is canonical.
93
+ - README entries should link to source and summarize the main parameters.
94
+ - If a payload shape is shown in docs or validated by tests, keep its reusable source in the relevant module under `gdc-common-utils-ts/examples`.
@@ -0,0 +1,70 @@
1
+ import { ProfileManager } from './ProfileManager.js';
2
+ import { ProfileRegistry } from './ProfileRegistry.js';
3
+ import type { AppInfo, InitializeSessionParams, IVerifier, IVaultRepository, ProfileRegistryEntry, SdkConfig } from './types.js';
4
+ /**
5
+ * Frontend-facing SDK entry point for profile/session bootstrapping, lightweight
6
+ * provider discovery, and role-scoped session creation.
7
+ *
8
+ * This class is intentionally small while the convergence work is still in
9
+ * progress. It should be treated as the bootstrap façade, not yet the full
10
+ * replacement for every legacy runtime helper.
11
+ *
12
+ * Canonical frontend payload examples used by tests and docs live in:
13
+ * `gdc-common-utils-ts/examples`
14
+ */
15
+ export declare class ClientSDK {
16
+ private readonly sdkConfig;
17
+ private readonly appInfo;
18
+ private readonly _wallet;
19
+ private readonly _verifier;
20
+ private readonly _icaDid?;
21
+ private readonly mockDidDocuments;
22
+ currentSession: ProfileManager | null;
23
+ profileRegistry: ProfileRegistry | null;
24
+ /**
25
+ * @param sdkConfig Frontend runtime adapters such as fetch/network/api.
26
+ * @param appInfo Information about the host app.
27
+ * @param _wallet Reserved wallet/provider dependency.
28
+ * @param _verifier DID/VC verifier dependency.
29
+ * @param _icaDid Optional bootstrap ICA DID used by the host app.
30
+ */
31
+ constructor(sdkConfig: SdkConfig, appInfo: AppInfo, _wallet: unknown, _verifier: IVerifier, _icaDid?: string | undefined);
32
+ /**
33
+ * Registers a mock DID document for local/demo discovery flows.
34
+ */
35
+ addMockDidDocument(did: string, didDoc: unknown): void;
36
+ /**
37
+ * Loads `/.well-known/api-config.json` from a provider URL or `did:web`.
38
+ */
39
+ fetchWellKnownApiConfig(source: string): Promise<Record<string, unknown>>;
40
+ /**
41
+ * Loads `/.well-known/supported-fields.json` from a provider URL or `did:web`.
42
+ */
43
+ fetchSupportedFields(source: string): Promise<Array<{
44
+ code: string;
45
+ display: string;
46
+ }>>;
47
+ /**
48
+ * Initializes a profile-scoped session and returns a `ProfileManager` with the
49
+ * role-specific services available for the current profile.
50
+ *
51
+ * Implemented today:
52
+ * - canonical profile normalization and persistence bootstrap
53
+ * - provider DID carried into the created session
54
+ *
55
+ * Still pending:
56
+ * - explicit `deviceIdentity` / `actorIdentity` / `providerIdentity` stores
57
+ * - provider DID resolution through the shared discovery contracts
58
+ */
59
+ initializeSession(params: InitializeSessionParams, createVaultForProfile: () => IVaultRepository): Promise<ProfileManager>;
60
+ /**
61
+ * Initializes the local profile registry abstraction.
62
+ */
63
+ initializeProfileRegistry(createVaultForProfile: () => IVaultRepository): Promise<ProfileRegistry>;
64
+ /**
65
+ * Clears the current in-memory session reference.
66
+ */
67
+ shutdownSession(): void;
68
+ private resolveBaseUrl;
69
+ }
70
+ export type { InitializeSessionParams, ProfileRegistryEntry, };
@@ -0,0 +1,140 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ import { ProfileManager } from './ProfileManager.js';
3
+ import { ProfileRegistry } from './ProfileRegistry.js';
4
+ /**
5
+ * Frontend-facing SDK entry point for profile/session bootstrapping, lightweight
6
+ * provider discovery, and role-scoped session creation.
7
+ *
8
+ * This class is intentionally small while the convergence work is still in
9
+ * progress. It should be treated as the bootstrap façade, not yet the full
10
+ * replacement for every legacy runtime helper.
11
+ *
12
+ * Canonical frontend payload examples used by tests and docs live in:
13
+ * `gdc-common-utils-ts/examples`
14
+ */
15
+ export class ClientSDK {
16
+ /**
17
+ * @param sdkConfig Frontend runtime adapters such as fetch/network/api.
18
+ * @param appInfo Information about the host app.
19
+ * @param _wallet Reserved wallet/provider dependency.
20
+ * @param _verifier DID/VC verifier dependency.
21
+ * @param _icaDid Optional bootstrap ICA DID used by the host app.
22
+ */
23
+ constructor(sdkConfig, appInfo, _wallet, _verifier, _icaDid) {
24
+ this.sdkConfig = sdkConfig;
25
+ this.appInfo = appInfo;
26
+ this._wallet = _wallet;
27
+ this._verifier = _verifier;
28
+ this._icaDid = _icaDid;
29
+ this.mockDidDocuments = new Map();
30
+ this.currentSession = null;
31
+ this.profileRegistry = null;
32
+ }
33
+ /**
34
+ * Registers a mock DID document for local/demo discovery flows.
35
+ */
36
+ addMockDidDocument(did, didDoc) {
37
+ this.mockDidDocuments.set(String(did || '').trim(), didDoc);
38
+ }
39
+ /**
40
+ * Loads `/.well-known/api-config.json` from a provider URL or `did:web`.
41
+ */
42
+ async fetchWellKnownApiConfig(source) {
43
+ const baseUrl = await this.resolveBaseUrl(source);
44
+ const response = await this.sdkConfig.fetcher(new URL('.well-known/api-config.json', baseUrl).href);
45
+ if (!response.ok) {
46
+ throw new Error(`Failed to load API config (${response.status}).`);
47
+ }
48
+ return response.json();
49
+ }
50
+ /**
51
+ * Loads `/.well-known/supported-fields.json` from a provider URL or `did:web`.
52
+ */
53
+ async fetchSupportedFields(source) {
54
+ const baseUrl = await this.resolveBaseUrl(source);
55
+ const response = await this.sdkConfig.fetcher(new URL('.well-known/supported-fields.json', baseUrl).href);
56
+ if (!response.ok)
57
+ return [];
58
+ const body = await response.json();
59
+ const candidates = body.fields || body.supportedFields || [];
60
+ if (!Array.isArray(candidates))
61
+ return [];
62
+ return candidates
63
+ .map((entry) => {
64
+ if (!entry || typeof entry !== 'object')
65
+ return null;
66
+ const code = String(entry.code || '').trim();
67
+ const display = String(entry.display || code).trim();
68
+ return code ? { code, display } : null;
69
+ })
70
+ .filter((entry) => Boolean(entry));
71
+ }
72
+ /**
73
+ * Initializes a profile-scoped session and returns a `ProfileManager` with the
74
+ * role-specific services available for the current profile.
75
+ *
76
+ * Implemented today:
77
+ * - canonical profile normalization and persistence bootstrap
78
+ * - provider DID carried into the created session
79
+ *
80
+ * Still pending:
81
+ * - explicit `deviceIdentity` / `actorIdentity` / `providerIdentity` stores
82
+ * - provider DID resolution through the shared discovery contracts
83
+ */
84
+ async initializeSession(params, createVaultForProfile) {
85
+ this.shutdownSession();
86
+ const vault = createVaultForProfile();
87
+ await vault.initialize();
88
+ const profile = {
89
+ id: String(params.profileId || '').trim(),
90
+ email: String(params.email || '').trim(),
91
+ role: String(params.role || '').trim(),
92
+ providerDid: String(params.providerDid || '').trim(),
93
+ appType: params.appType,
94
+ createdAt: new Date().toISOString(),
95
+ };
96
+ if (!profile.id) {
97
+ throw new Error('initializeSession requires profileId.');
98
+ }
99
+ await vault.put('profile', profile);
100
+ const session = new ProfileManager(profile, profile.providerDid);
101
+ this.currentSession = session;
102
+ return session;
103
+ }
104
+ /**
105
+ * Initializes the local profile registry abstraction.
106
+ */
107
+ async initializeProfileRegistry(createVaultForProfile) {
108
+ const vault = createVaultForProfile();
109
+ const registry = new ProfileRegistry(vault);
110
+ await registry.initialize();
111
+ this.profileRegistry = registry;
112
+ return registry;
113
+ }
114
+ /**
115
+ * Clears the current in-memory session reference.
116
+ */
117
+ shutdownSession() {
118
+ this.currentSession = null;
119
+ }
120
+ async resolveBaseUrl(source) {
121
+ const raw = String(source || '').trim();
122
+ if (!raw)
123
+ throw new Error('Provider source is required.');
124
+ if (raw.startsWith('did:web:')) {
125
+ const didDoc = this.mockDidDocuments.get(raw);
126
+ const didServices = (didDoc?.service && Array.isArray(didDoc.service) ? didDoc.service : []);
127
+ const endpoint = didServices
128
+ .map((service) => service.serviceEndpoint)
129
+ .find((candidate) => typeof candidate === 'string' && candidate.startsWith('http'));
130
+ if (endpoint)
131
+ return new URL(String(endpoint));
132
+ const host = raw.replace(/^did:web:/, '').replace(/:/g, '/');
133
+ return new URL(`https://${host}/`);
134
+ }
135
+ if (/^https?:\/\//i.test(raw)) {
136
+ return new URL(raw.endsWith('/') ? raw : `${raw}/`);
137
+ }
138
+ return new URL(`https://${raw}/`);
139
+ }
140
+ }
@@ -0,0 +1,140 @@
1
+ import type { DeviceAppType, DeviceUserClass } from 'gdc-common-utils-ts/constants';
2
+ import type { Profile } from './types.js';
3
+ import type { CommonServices, FamilyAdminServices, IndividualServices, OrgAdminServices, ProfessionalServices } from './roleRegistry.js';
4
+ /**
5
+ * Role-scoped session object returned by `ClientSDK.initializeSession(...)`.
6
+ *
7
+ * It exposes the common/auth surface plus the services allowed by the current
8
+ * profile capabilities.
9
+ */
10
+ export declare class ProfileManager {
11
+ readonly profile: Profile;
12
+ readonly orgDidDoc: {
13
+ id: string;
14
+ };
15
+ readonly common: CommonServices;
16
+ readonly orgAdmin?: OrgAdminServices;
17
+ readonly familyAdmin?: FamilyAdminServices;
18
+ readonly individual?: IndividualServices;
19
+ readonly professional?: ProfessionalServices;
20
+ /**
21
+ * @param profile Current logical profile.
22
+ * @param orgDid DID of the provider/organization used as the session anchor.
23
+ */
24
+ constructor(profile: Profile, orgDid: string);
25
+ /**
26
+ * Organization-admin helper for employee/professional creation.
27
+ */
28
+ createOrganizationEmployee(providerDid: string, idToken: string, params: {
29
+ email: string;
30
+ role: string;
31
+ userClass?: DeviceUserClass;
32
+ type?: DeviceAppType;
33
+ }): Promise<{
34
+ thid: string;
35
+ }>;
36
+ /**
37
+ * Family/individual-admin helper for subject organization/index bootstrap.
38
+ */
39
+ bootstrapSubjectOrganizationIndex(params: {
40
+ registrationClaims: object;
41
+ providerDid: string;
42
+ idToken: string;
43
+ acceptedOfferId?: string;
44
+ }): Promise<{
45
+ registrationThid: string;
46
+ confirmationThid?: string;
47
+ }>;
48
+ /**
49
+ * Individual-service helper to import a FHIR payload or IPS bundle.
50
+ */
51
+ importIpsOrFhirAndUpdateIndex(params: {
52
+ compositionPayload: object;
53
+ providerDid: string;
54
+ requiredScope: string;
55
+ idToken: string;
56
+ format?: 'org.hl7.fhir.r4' | 'org.hl7.fhir.api';
57
+ }): Promise<{
58
+ thid: string;
59
+ }>;
60
+ /**
61
+ * Individual-service helper to create a consent-based access grant for a professional.
62
+ */
63
+ grantProfessionalAccess(params: {
64
+ subjectDid?: string;
65
+ /**
66
+ * Compatibility/extension field.
67
+ *
68
+ * CORE canonical consent examples identify the subject with `subjectDid`.
69
+ */
70
+ subjectPhone?: string;
71
+ /**
72
+ * Compatibility/extension display hint for phone-oriented UX flows.
73
+ */
74
+ subjectGivenName?: string;
75
+ /**
76
+ * Canonical flat consent actor identifier input.
77
+ *
78
+ * Preferred forms:
79
+ * - `did:web:...`
80
+ * - `user@example.org`
81
+ * - `tel:+34600111222`
82
+ * - `ES`
83
+ * - comma-separated list or string array of those values
84
+ *
85
+ * A legacy structured object is still accepted for compatibility.
86
+ */
87
+ actorId?: string | string[] | {
88
+ didWeb?: string;
89
+ organizationUrl?: string;
90
+ organizationTaxId?: string;
91
+ email?: string;
92
+ phone?: string;
93
+ };
94
+ /**
95
+ * @deprecated Use `actorId`.
96
+ */
97
+ actor?: string | string[] | {
98
+ didWeb?: string;
99
+ organizationUrl?: string;
100
+ organizationTaxId?: string;
101
+ email?: string;
102
+ phone?: string;
103
+ };
104
+ actorRole: string;
105
+ purpose: string;
106
+ actions: string[];
107
+ providerDid: string;
108
+ requiredScope: string;
109
+ idToken: string;
110
+ consentIdentifier?: string;
111
+ consentDate?: string;
112
+ decision?: 'permit' | 'deny';
113
+ attachmentContentType?: string;
114
+ attachmentBase64?: string;
115
+ }): Promise<{
116
+ thid: string;
117
+ subjectIdentifier: string;
118
+ actorIdentifier: string;
119
+ consentClaims: Record<string, unknown>;
120
+ claimsCid?: string;
121
+ }>;
122
+ /**
123
+ * Individual-service helper to generate a digital twin projection from subject data.
124
+ */
125
+ generateDigitalTwinFromSubjectData(params: {
126
+ compositionPayload: object;
127
+ providerDid: string;
128
+ requiredScope: string;
129
+ idToken: string;
130
+ format?: 'org.hl7.fhir.r4' | 'org.hl7.fhir.api';
131
+ }): Promise<{
132
+ thid: string;
133
+ }>;
134
+ }
135
+ /**
136
+ * Preferred neutral frontend actor-session surface.
137
+ *
138
+ * Keep `ProfileManager` for compatibility with earlier app-facing terminology.
139
+ */
140
+ export { ProfileManager as ActorSession };
@@ -0,0 +1,76 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ import { CommonAuthService } from './services.js';
3
+ import { mapCapabilitiesToServices } from './capabilityMapper.js';
4
+ /**
5
+ * Role-scoped session object returned by `ClientSDK.initializeSession(...)`.
6
+ *
7
+ * It exposes the common/auth surface plus the services allowed by the current
8
+ * profile capabilities.
9
+ */
10
+ export class ProfileManager {
11
+ /**
12
+ * @param profile Current logical profile.
13
+ * @param orgDid DID of the provider/organization used as the session anchor.
14
+ */
15
+ constructor(profile, orgDid) {
16
+ this.profile = profile;
17
+ this.orgDidDoc = { id: orgDid };
18
+ this.common = { auth: new CommonAuthService() };
19
+ const mapped = mapCapabilitiesToServices(profile, profile.appType);
20
+ this.orgAdmin = mapped.orgAdmin;
21
+ this.familyAdmin = mapped.familyAdmin;
22
+ this.individual = mapped.individual;
23
+ this.professional = mapped.professional;
24
+ }
25
+ /**
26
+ * Organization-admin helper for employee/professional creation.
27
+ */
28
+ async createOrganizationEmployee(providerDid, idToken, params) {
29
+ if (!this.orgAdmin?.admin) {
30
+ throw new Error('orgAdmin.admin service is not available for this profile.');
31
+ }
32
+ return this.orgAdmin.admin.createOrganizationEmployee(providerDid, idToken, params);
33
+ }
34
+ /**
35
+ * Family/individual-admin helper for subject organization/index bootstrap.
36
+ */
37
+ async bootstrapSubjectOrganizationIndex(params) {
38
+ if (!this.familyAdmin?.admin) {
39
+ throw new Error('familyAdmin.admin service is not available for this profile.');
40
+ }
41
+ return this.familyAdmin.admin.bootstrapSubjectOrganizationIndex(params);
42
+ }
43
+ /**
44
+ * Individual-service helper to import a FHIR payload or IPS bundle.
45
+ */
46
+ async importIpsOrFhirAndUpdateIndex(params) {
47
+ if (!this.individual?.service) {
48
+ throw new Error('individual.service is not available for this profile.');
49
+ }
50
+ return this.individual.service.importIpsOrFhirAndUpdateIndex(params.compositionPayload, params.providerDid, params.requiredScope, params.idToken, params.format);
51
+ }
52
+ /**
53
+ * Individual-service helper to create a consent-based access grant for a professional.
54
+ */
55
+ async grantProfessionalAccess(params) {
56
+ if (!this.individual?.service) {
57
+ throw new Error('individual.service is not available for this profile.');
58
+ }
59
+ return this.individual.service.grantProfessionalAccess(params);
60
+ }
61
+ /**
62
+ * Individual-service helper to generate a digital twin projection from subject data.
63
+ */
64
+ async generateDigitalTwinFromSubjectData(params) {
65
+ if (!this.individual?.service) {
66
+ throw new Error('individual.service is not available for this profile.');
67
+ }
68
+ return this.individual.service.generateDigitalTwinFromSubjectData(params.compositionPayload, params.providerDid, params.requiredScope, params.idToken, params.format);
69
+ }
70
+ }
71
+ /**
72
+ * Preferred neutral frontend actor-session surface.
73
+ *
74
+ * Keep `ProfileManager` for compatibility with earlier app-facing terminology.
75
+ */
76
+ export { ProfileManager as ActorSession };
@@ -0,0 +1,11 @@
1
+ import type { IVaultRepository, ProfileRegistryEntry } from './types.js';
2
+ export declare class ProfileRegistry {
3
+ private readonly vault;
4
+ constructor(vault: IVaultRepository);
5
+ initialize(): Promise<void>;
6
+ register(entry: ProfileRegistryEntry): Promise<void>;
7
+ upsert(entry: ProfileRegistryEntry): Promise<ProfileRegistryEntry>;
8
+ list(): Promise<ProfileRegistryEntry[]>;
9
+ get(id: string): Promise<ProfileRegistryEntry | undefined>;
10
+ remove(id: string): Promise<boolean>;
11
+ }
@@ -0,0 +1,26 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ const COLLECTION = 'profiles';
3
+ export class ProfileRegistry {
4
+ constructor(vault) {
5
+ this.vault = vault;
6
+ }
7
+ async initialize() {
8
+ await this.vault.initialize();
9
+ }
10
+ async register(entry) {
11
+ await this.vault.put(COLLECTION, entry);
12
+ }
13
+ async upsert(entry) {
14
+ await this.vault.put(COLLECTION, entry);
15
+ return entry;
16
+ }
17
+ async list() {
18
+ return this.vault.query(COLLECTION, {});
19
+ }
20
+ async get(id) {
21
+ return this.vault.get(COLLECTION, id);
22
+ }
23
+ async remove(id) {
24
+ return this.vault.delete(COLLECTION, id);
25
+ }
26
+ }
@@ -0,0 +1,6 @@
1
+ import type { IVerifier } from './types.js';
2
+ export declare class VerifierService implements IVerifier {
3
+ constructor(_cryptographyService?: unknown, _rootGoverningKeyPub?: unknown, _fetcher?: typeof fetch);
4
+ verifyCredential(): Promise<boolean>;
5
+ verifyPresentation(): Promise<boolean>;
6
+ }
@@ -0,0 +1,10 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ export class VerifierService {
3
+ constructor(_cryptographyService, _rootGoverningKeyPub, _fetcher) { }
4
+ async verifyCredential() {
5
+ return true;
6
+ }
7
+ async verifyPresentation() {
8
+ return true;
9
+ }
10
+ }
@@ -0,0 +1,2 @@
1
+ export type { ActorFacadeDescriptor, ActorKind, ActorSessionDescriptor, Capability, } from '../../gdc-sdk-core-ts/dist/index.js';
2
+ export { expandActorSessionDescriptorToFacades, filterCapabilitiesForActor, } from '../../gdc-sdk-core-ts/dist/index.js';
@@ -0,0 +1,2 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ export { expandActorSessionDescriptorToFacades, filterCapabilitiesForActor, } from '../../gdc-sdk-core-ts/dist/index.js';
@@ -0,0 +1,8 @@
1
+ import type { Profile } from './types.js';
2
+ import type { FamilyAdminServices, IndividualServices, OrgAdminServices, ProfessionalServices } from './roleRegistry.js';
3
+ export declare function mapCapabilitiesToServices(profile: Profile, appType: 'Organization' | 'Family'): {
4
+ professional?: ProfessionalServices;
5
+ orgAdmin?: OrgAdminServices;
6
+ familyAdmin?: FamilyAdminServices;
7
+ individual?: IndividualServices;
8
+ };
@@ -0,0 +1,28 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ import { HealthcareActorRoleCodes } from 'gdc-common-utils-ts/constants';
3
+ import { FamilyAdminService, IndividualService, OrgAdminService, ParamedicService, PhysicianService } from './services.js';
4
+ export function mapCapabilitiesToServices(profile, appType) {
5
+ const role = String(profile.role || '').toLowerCase();
6
+ const code = role.includes('|') ? role.split('|')[1] : role;
7
+ const isController = code === 'controller' || code === 'resprsn' || code === HealthcareActorRoleCodes.Controller;
8
+ const isPhysician = code === HealthcareActorRoleCodes.PhysicianBroad || code === HealthcareActorRoleCodes.Physician || code === 'physician';
9
+ const isParamedic = code === HealthcareActorRoleCodes.Paramedic || code === 'paramedic';
10
+ const professional = {};
11
+ const orgAdmin = {};
12
+ const familyAdmin = {};
13
+ const individual = {};
14
+ if (appType === 'Organization' && isController) {
15
+ orgAdmin.admin = new OrgAdminService();
16
+ }
17
+ if (appType === 'Family' && isController) {
18
+ familyAdmin.admin = new FamilyAdminService();
19
+ individual.service = new IndividualService();
20
+ }
21
+ if (isPhysician) {
22
+ professional.physician = new PhysicianService();
23
+ }
24
+ if (isParamedic) {
25
+ professional.paramedic = new ParamedicService();
26
+ }
27
+ return { professional, orgAdmin, familyAdmin, individual };
28
+ }
@@ -0,0 +1,12 @@
1
+ export * from '../../gdc-sdk-core-ts/dist/index.js';
2
+ export * from './runtime-contracts.js';
3
+ export * from './actor-session.js';
4
+ export * from './session-descriptor.js';
5
+ export * from './types.js';
6
+ export * from './services.js';
7
+ export * from './roleRegistry.js';
8
+ export * from './capabilityMapper.js';
9
+ export * from './VerifierService.js';
10
+ export * from './ProfileManager.js';
11
+ export * from './ProfileRegistry.js';
12
+ export * from './ClientSDK.js';
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ export * from '../../gdc-sdk-core-ts/dist/index.js';
3
+ export * from './runtime-contracts.js';
4
+ export * from './actor-session.js';
5
+ export * from './session-descriptor.js';
6
+ export * from './types.js';
7
+ export * from './services.js';
8
+ export * from './roleRegistry.js';
9
+ export * from './capabilityMapper.js';
10
+ export * from './VerifierService.js';
11
+ export * from './ProfileManager.js';
12
+ export * from './ProfileRegistry.js';
13
+ export * from './ClientSDK.js';
@@ -0,0 +1,19 @@
1
+ import { CommonAuthService, FamilyAdminService, IndividualService, OrgAdminService, ParamedicService, PhysicianService } from './services.js';
2
+ export interface OrgAdminServices {
3
+ admin?: OrgAdminService;
4
+ it?: unknown;
5
+ }
6
+ export interface FamilyAdminServices {
7
+ admin?: FamilyAdminService;
8
+ it?: unknown;
9
+ }
10
+ export interface IndividualServices {
11
+ service?: IndividualService;
12
+ }
13
+ export interface ProfessionalServices {
14
+ physician?: PhysicianService;
15
+ paramedic?: ParamedicService;
16
+ }
17
+ export interface CommonServices {
18
+ auth: CommonAuthService;
19
+ }
@@ -0,0 +1,2 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ export {};
@@ -0,0 +1,22 @@
1
+ import type { DataPersistencePolicy } from '../../gdc-sdk-core-ts/dist/index.js';
2
+ export type LegacyFrontSourcePackage = never;
3
+ export type FrontRuntimeKind = 'expo' | 'web' | 'react-native';
4
+ export type FrontFetchLike = typeof fetch;
5
+ export type FrontRuntimeConfig = {
6
+ runtimeKind: FrontRuntimeKind;
7
+ fetcher: FrontFetchLike;
8
+ persistencePolicy?: DataPersistencePolicy;
9
+ cryptoProvider?: unknown;
10
+ networkProvider?: unknown;
11
+ secureStorageProvider?: unknown;
12
+ vaultFactory?: unknown;
13
+ outboxRepositoryFactory?: unknown;
14
+ oidcProvider?: unknown;
15
+ };
16
+ export type FrontPackageStatus = {
17
+ packageName: 'gdc-sdk-front-ts';
18
+ dependsOnCorePackage: 'gdc-sdk-core-ts';
19
+ legacySourcePackages: LegacyFrontSourcePackage[];
20
+ status: 'bootstrap';
21
+ };
22
+ export declare const GDC_SDK_FRONT_STATUS: FrontPackageStatus;
@@ -0,0 +1,7 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ export const GDC_SDK_FRONT_STATUS = {
3
+ packageName: 'gdc-sdk-front-ts',
4
+ dependsOnCorePackage: 'gdc-sdk-core-ts',
5
+ legacySourcePackages: [],
6
+ status: 'bootstrap',
7
+ };
@@ -0,0 +1,167 @@
1
+ import type { DeviceAppType, DeviceUserClass } from 'gdc-common-utils-ts/constants';
2
+ export declare class CommonAuthService {
3
+ activateDevice(_licenseCode: string, _providerDid: string, _idToken: string): Promise<{
4
+ thid: string;
5
+ }>;
6
+ }
7
+ export declare class OrgAdminService {
8
+ createOrganizationEmployee(_providerDid: string, _idToken: string, _params: {
9
+ email: string;
10
+ role: string;
11
+ userClass?: DeviceUserClass;
12
+ type?: DeviceAppType;
13
+ }): Promise<{
14
+ thid: string;
15
+ }>;
16
+ }
17
+ export declare class FamilyAdminService {
18
+ bootstrapSubjectOrganizationIndex(_params: {
19
+ registrationClaims: object;
20
+ providerDid: string;
21
+ idToken: string;
22
+ acceptedOfferId?: string;
23
+ }): Promise<{
24
+ registrationThid: string;
25
+ confirmationThid?: string;
26
+ }>;
27
+ }
28
+ export declare class IndividualService {
29
+ /**
30
+ * Imports a document/FHIR payload for subject indexing.
31
+ *
32
+ * Canonical example input lives in:
33
+ * `gdc-common-utils-ts/examples`
34
+ */
35
+ importIpsOrFhirAndUpdateIndex(_compositionPayload: object, _providerDid: string, _requiredScope: string, _idToken: string, _format?: 'org.hl7.fhir.r4' | 'org.hl7.fhir.api'): Promise<{
36
+ thid: string;
37
+ }>;
38
+ grantProfessionalAccess(_params: {
39
+ subjectDid?: string;
40
+ /**
41
+ * Compatibility/extension field.
42
+ *
43
+ * CORE canonical consent examples identify the subject with `subjectDid`.
44
+ * Phone-based consent targeting belongs to extension layers, not the base
45
+ * CORE GW contract.
46
+ */
47
+ subjectPhone?: string;
48
+ /**
49
+ * Compatibility/extension display hint.
50
+ *
51
+ * Keep this only for UX layers that still surface phone/notification flows.
52
+ * CORE canonical examples do not require it.
53
+ */
54
+ subjectGivenName?: string;
55
+ /**
56
+ * Canonical flat consent actor identifier input.
57
+ *
58
+ * Preferred forms:
59
+ * - `did:web:...`
60
+ * - `user@example.org`
61
+ * - `tel:+34600111222`
62
+ * - `ES`
63
+ * - comma-separated list or string array of those values
64
+ *
65
+ * A legacy structured object is still accepted for compatibility.
66
+ */
67
+ actorId?: string | string[] | {
68
+ didWeb?: string;
69
+ organizationUrl?: string;
70
+ organizationTaxId?: string;
71
+ email?: string;
72
+ phone?: string;
73
+ };
74
+ /**
75
+ * @deprecated Use `actorId`.
76
+ */
77
+ actor?: string | string[] | {
78
+ didWeb?: string;
79
+ organizationUrl?: string;
80
+ organizationTaxId?: string;
81
+ email?: string;
82
+ phone?: string;
83
+ };
84
+ actorRole: string;
85
+ purpose: string;
86
+ actions: string[];
87
+ providerDid: string;
88
+ requiredScope: string;
89
+ idToken: string;
90
+ consentIdentifier?: string;
91
+ consentDate?: string;
92
+ decision?: 'permit' | 'deny';
93
+ attachmentContentType?: string;
94
+ attachmentBase64?: string;
95
+ }): Promise<{
96
+ thid: string;
97
+ subjectIdentifier: string;
98
+ actorIdentifier: string;
99
+ consentClaims: Record<string, unknown>;
100
+ claimsCid?: string;
101
+ }>;
102
+ generateDigitalTwinFromSubjectData(_compositionPayload: object, _providerDid: string, _requiredScope: string, _idToken: string, _format?: 'org.hl7.fhir.r4' | 'org.hl7.fhir.api'): Promise<{
103
+ thid: string;
104
+ }>;
105
+ /**
106
+ * Sends a lightweight communication request description.
107
+ *
108
+ * Canonical example input lives in:
109
+ * `gdc-common-utils-ts/examples`
110
+ */
111
+ sendCommunication(_communication: {
112
+ thid?: string;
113
+ pthid?: string;
114
+ channelId?: string;
115
+ partOf?: string;
116
+ subject: string;
117
+ text?: string;
118
+ sender?: string;
119
+ recipient?: string | string[];
120
+ sent?: string;
121
+ category?: string | string[];
122
+ attachments?: Array<{
123
+ contentType?: string;
124
+ title?: string;
125
+ dataBase64?: string;
126
+ url?: string;
127
+ }>;
128
+ claims?: Record<string, unknown>;
129
+ }, _providerDid: string, _requiredScope: string, _idToken: string, _format?: 'org.hl7.fhir.r4' | 'org.hl7.fhir.api'): Promise<{
130
+ thid: string;
131
+ }>;
132
+ /**
133
+ * Builds a lightweight clinical bundle search request description.
134
+ *
135
+ * Canonical example input lives in:
136
+ * `gdc-common-utils-ts/examples`
137
+ */
138
+ searchClinicalBundle(_query: {
139
+ subject: string;
140
+ section?: string | string[];
141
+ includedTypes?: string[];
142
+ date?: {
143
+ start?: string;
144
+ end?: string;
145
+ };
146
+ code?: string | string[];
147
+ category?: string | string[];
148
+ author?: string | string[];
149
+ thid?: string;
150
+ pthid?: string;
151
+ channelId?: string;
152
+ partOf?: string;
153
+ searchParams?: Record<string, string | number | boolean | undefined>;
154
+ }, _providerDid: string, _requiredScope: string, _idToken: string): Promise<{
155
+ thid: string;
156
+ }>;
157
+ getLatestIps(_subject: string, _providerDid: string, _requiredScope: string, _idToken: string, _date?: {
158
+ start?: string;
159
+ end?: string;
160
+ }): Promise<{
161
+ thid: string;
162
+ }>;
163
+ }
164
+ export declare class PhysicianService {
165
+ }
166
+ export declare class ParamedicService {
167
+ }
@@ -0,0 +1,78 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ function requireNonEmptyText(value, fieldName) {
3
+ const normalized = String(value ?? '').trim();
4
+ if (!normalized) {
5
+ throw new Error(`${fieldName} is required.`);
6
+ }
7
+ return normalized;
8
+ }
9
+ export class CommonAuthService {
10
+ async activateDevice(_licenseCode, _providerDid, _idToken) {
11
+ return { thid: `thid-${Date.now()}` };
12
+ }
13
+ }
14
+ export class OrgAdminService {
15
+ async createOrganizationEmployee(_providerDid, _idToken, _params) {
16
+ return { thid: `thid-${Date.now()}` };
17
+ }
18
+ }
19
+ export class FamilyAdminService {
20
+ async bootstrapSubjectOrganizationIndex(_params) {
21
+ return { registrationThid: `thid-${Date.now()}` };
22
+ }
23
+ }
24
+ export class IndividualService {
25
+ /**
26
+ * Imports a document/FHIR payload for subject indexing.
27
+ *
28
+ * Canonical example input lives in:
29
+ * `gdc-common-utils-ts/examples`
30
+ */
31
+ async importIpsOrFhirAndUpdateIndex(_compositionPayload, _providerDid, _requiredScope, _idToken, _format) {
32
+ return { thid: `thid-${Date.now()}` };
33
+ }
34
+ async grantProfessionalAccess(_params) {
35
+ return {
36
+ thid: `thid-${Date.now()}`,
37
+ subjectIdentifier: '',
38
+ actorIdentifier: '',
39
+ consentClaims: {},
40
+ };
41
+ }
42
+ async generateDigitalTwinFromSubjectData(_compositionPayload, _providerDid, _requiredScope, _idToken, _format) {
43
+ return { thid: `thid-${Date.now()}` };
44
+ }
45
+ /**
46
+ * Sends a lightweight communication request description.
47
+ *
48
+ * Canonical example input lives in:
49
+ * `gdc-common-utils-ts/examples`
50
+ */
51
+ async sendCommunication(_communication, _providerDid, _requiredScope, _idToken, _format) {
52
+ requireNonEmptyText(_communication?.subject, 'sendCommunication subject');
53
+ requireNonEmptyText(_providerDid, 'sendCommunication providerDid');
54
+ requireNonEmptyText(_requiredScope, 'sendCommunication requiredScope');
55
+ requireNonEmptyText(_idToken, 'sendCommunication idToken');
56
+ return { thid: `thid-${Date.now()}` };
57
+ }
58
+ /**
59
+ * Builds a lightweight clinical bundle search request description.
60
+ *
61
+ * Canonical example input lives in:
62
+ * `gdc-common-utils-ts/examples`
63
+ */
64
+ async searchClinicalBundle(_query, _providerDid, _requiredScope, _idToken) {
65
+ requireNonEmptyText(_query?.subject, 'searchClinicalBundle subject');
66
+ requireNonEmptyText(_providerDid, 'searchClinicalBundle providerDid');
67
+ requireNonEmptyText(_requiredScope, 'searchClinicalBundle requiredScope');
68
+ requireNonEmptyText(_idToken, 'searchClinicalBundle idToken');
69
+ return { thid: `thid-${Date.now()}` };
70
+ }
71
+ async getLatestIps(_subject, _providerDid, _requiredScope, _idToken, _date) {
72
+ return { thid: `thid-${Date.now()}` };
73
+ }
74
+ }
75
+ export class PhysicianService {
76
+ }
77
+ export class ParamedicService {
78
+ }
@@ -0,0 +1,11 @@
1
+ import type { ActorFlags, ActorFacadeDescriptor, ActorSessionDescriptor } from '../../gdc-sdk-core-ts/dist/index.js';
2
+ export type FrontActorFlags = ActorFlags;
3
+ export type FrontSessionDescriptorInput = {
4
+ appType: 'Organization' | 'Family';
5
+ profileId: string;
6
+ profileDid?: string;
7
+ role?: string;
8
+ actorFlags: FrontActorFlags;
9
+ };
10
+ export declare function describeFrontActorSession(input: FrontSessionDescriptorInput): ActorSessionDescriptor;
11
+ export declare function describeFrontActorFacades(input: FrontSessionDescriptorInput): ActorFacadeDescriptor[];
@@ -0,0 +1,8 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ import { buildActorSessionDescriptorFromActorFlags, expandActorSessionDescriptorToFacades, } from '../../gdc-sdk-core-ts/dist/index.js';
3
+ export function describeFrontActorSession(input) {
4
+ return buildActorSessionDescriptorFromActorFlags(input);
5
+ }
6
+ export function describeFrontActorFacades(input) {
7
+ return expandActorSessionDescriptorToFacades(describeFrontActorSession(input));
8
+ }
@@ -0,0 +1,11 @@
1
+ import type { IApiConfig, INetwork, BundleSearchQuery, CommunicationInput, DateRange } from '../../gdc-sdk-core-ts/dist/index.js';
2
+ export type { AppInfo, InitializeSessionParams, Profile, ProfileRegistryEntry, VaultQueryCondition, VaultQuery, IVaultRepository, IApiConfig, INetwork, IVerifier } from '../../gdc-sdk-core-ts/dist/index.js';
3
+ export type SdkConfig = {
4
+ crypto?: unknown;
5
+ network: INetwork;
6
+ api: IApiConfig;
7
+ fetcher: typeof fetch;
8
+ };
9
+ export type FrontDateRange = DateRange;
10
+ export type FrontBundleSearchQuery = BundleSearchQuery;
11
+ export type FrontCommunicationInput = CommunicationInput;
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "gdc-sdk-front-ts",
3
+ "version": "0.1.1",
4
+ "description": "Next-generation frontend runtime package for the GDC SDK family",
5
+ "license": "Apache-2.0",
6
+ "author": "Antifraud Services Inc.",
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc -p tsconfig.json",
15
+ "type-check": "tsc -p tsconfig.json --noEmit",
16
+ "test": "npm run build && node --test tests/*.test.mjs"
17
+ },
18
+ "dependencies": {
19
+ "@babel/runtime": "^7.28.4",
20
+ "gdc-common-utils-ts": "^1.4.22"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^20.14.10",
24
+ "typescript": "^5.5.4"
25
+ }
26
+ }