gdc-sdk-core-ts
v2.0.6
Published
Runtime-neutral actor and capability contracts for GDC SDK convergence
Downloads
5,804
Readme
gdc-sdk-core-ts
See ARCHITECTURE.md and CONTRIBUTING.md before adding or reshaping facades, profile contracts, or high-level tests.
Short rule:
101tests must be didactic and step by step- shared types and fixtures must come from
gdc-common-utils-tsinstead of being re-invented locally as literals
Runtime-neutral shared contracts and helpers for GDC SDK consumers.
This package is for code that needs to understand and build GDC business flows
without caring about gateway routes, host/... vs :tenantId/..., transport
adapters, or UNID-specific runtime details.
Actor Split
The shared SDK family starts by separating actor families, because the flows are not the same:
- organization side
- organization controller
- organization employee / professional member
- individual side
- individual controller
- individual member / self
- related person
- professional with consented access
This package is the shared business-contract layer for all of those actors. It does not execute runtime calls, but it defines or normalizes the payloads and evaluations they all depend on.
Start Here
If you are new and need to see real SDK initialization and real method usage, open these documents in this order:
- docs/101-SDK_PACKAGE_BOUNDARIES.md
Why
core,node, andfrontare separate packages, what each one owns, and why actor-scoped facades are enforced. - docs/V2_PROFILE_RUNTIME_MIGRATION.md
How the old
ProfileManagerandJobManagersurface should be split acrosscommon-utils,sdk-core,sdk-node, andsdk-frontin v2. - docs/101-SDK_FLOWS.md Business-flow map from actor split to consent, invitation, import, and SMART.
- docs/101-CONSENT_COMMUNICATION.md
How an already-edited consent bundle
Communicationmoves into draft and outbox. - docs/101-IPS_COMMUNICATION_OUTBOX.md
How an IPS request
Communicationfromcommon-utilsmoves into draft and outbox. - gdc-sdk-node-ts/docs/101-SDK_INTEGRATION.md
Real backend initialization with
initializeCommunicationIdentity(...),new NodeHttpClient(...), runtime facades, and step-by-step GW usage. - gdc-sdk-node-ts/docs/101-LIVE_GW_LOCAL.md Exact local TTY and Docker commands for running the SDK against a real local GW CORE.
- gdc-sdk-front-ts/docs/101-SDK_INTEGRATION.md
Real frontend/native initialization with
new ClientSDK(...),initializeSession(...), provider discovery, and profile/session bootstrap.
Important:
gdc-sdk-core-tsdoes not initialize a runtime client by itself.- Runtime initialization lives in
gdc-sdk-node-tsandgdc-sdk-front-ts. - Shared payload shapes and examples live in
gdc-common-utils-ts. - Communication/profile/device/BFF keys belong to runtime transport identity.
- Controller
publicKeyJwkbelongs to business/operation identity and must stay separate from runtime communication keys. - FHIR-like resources in these shared flows may carry
resource.meta.claims, which is a project-specific claims container and not part of base FHIR. - Package-boundary guidance lives in docs/101-SDK_PACKAGE_BOUNDARIES.md.
- Onboarding rule across the repo family: high-level surface first, lower-level builders second, raw wire payloads last.
Shared example files to open while reading those guides:
- gdc-common-utils-ts/src/examples/shared.ts
- gdc-common-utils-ts/src/examples/organization-controller.ts
- gdc-common-utils-ts/src/examples/individual-controller.ts
- gdc-common-utils-ts/src/examples/professional.ts
- gdc-common-utils-ts/src/examples/frontend-session.ts
- gdc-common-utils-ts/src/examples/relationship-access.ts
- gdc-common-utils-ts/src/examples/lifecycle.ts
- gdc-common-utils-ts/docs/101-LIFECYCLE.md
Flow Families
The SDK documentation must cover these families from the start:
Organization bootstrap and activation
- start legal-organization verification transaction
- activate organization from ICA proof
- confirm organization order / offer
- prepare legal organization controller bootstrap payloads
- always declare service capabilities during legal-organization activation
- use
orgControllerDidas the teaching name for the controller DID - prefer
organizationActivationas the local activation builder/result name in examples
Canonical shared onboarding order:
- prepare/submit host
Organization/_transaction - consume ICA result and submit host
Organization/_activate - confirm host
Order/_batch
The _transaction payload is runtime-neutral in this package; real fetch,
polling, and JOSE/DIDComm transport execution remain runtime concerns of
gdc-sdk-node-ts or gdc-sdk-front-ts.
Primary reusable examples:
Employee creation and employee invitation
- create employee payload
- issue employee activation / invitation path
- employee device activation
- employee SMART access
Primary reusable examples:
Individual organization bootstrap
- start individual organization
- confirm individual order / offer
- prepare controller-owned individual bootstrap payloads
Primary reusable examples:
Related person and professional access to individual
- create
RelatedPerson - grant access / create consent
- evaluate requested access
- detect missing permissions
- build permission-request
Communication - invite actor and accept invitation
Primary reusable examples:
- gdc-common-utils-ts/src/examples/related-person.ts
- gdc-common-utils-ts/src/examples/professional.ts
- gdc-common-utils-ts/docs/101-CONSENT_ACCESS.md
Permission lifecycle
- create/grant permissions
- edit or replace permissions
- enable / disable / delete permissions
- grouped permission views for controller UX
- permission-request notifications and lookup
Canonical lifecycle naming for all SDK-facing docs and examples:
enabledisabledelete
Do not teach new integrations with mixed public naming such as revoke,
suspend, or purge when the intended API concept is the common lifecycle.
Clinical data contribution and retrieval
- ingest
Communication - import documents/resources into the subject index
- search clinical bundles
- search latest IPS
- request SMART token for subject-scoped access
These flows may be executed by:
- professional
- individual controller
- related person with write permission
- caregiver or other actor with explicit allowed sections/actions
Main Flows
1. Consent access evaluation
Use this when an app or backend needs to answer:
- can this professional or related person access this subject now?
- what permissions are missing?
- how do I build the canonical permission-request
Communication?
Main helpers:
groupConsentsForControllerView(...)evaluateRequestedAccess(...)getMissingPermissions(...)buildPermissionRequestCommunication(...)buildPermissionRequestCommunicationLookupQuery(...)
Reference:
2. Relationship invitation and acceptance
Use this when a controller invites a related person or professional to
connect with an individual or other subject.
The shared flow is:
- controller creates invitation payload
- invitee starts OTP challenge
- invitee confirms OTP
- invitee sets relationship PIN if required
- relationship channel becomes active
Main helpers:
createRelationshipChannelInvitationInput(...)createRelationshipChannelInvitationSummary(...)createRelationshipChannelOtpStartInput(...)createRelationshipChannelOtpConfirmInput(...)createRelationshipChannelOtpChallengeSummary(...)createRelationshipPinPolicy(...)createRelationshipPinSetInput(...)createRelationshipPinVerifyInput(...)createRelationshipLocalKeyEnvelope(...)
What this package does:
- validates and normalizes the shared payloads
- keeps the contract stable across portal, app, and phone-channel consumers
What this package does not do:
- call GW endpoints
- manage OTP providers
- store PIN hashes
- know anything about UNID reminder
Taskruntime
3. Communication and document handling
Use this when an app needs to build or read canonical Communication payloads
and attached clinical documents.
Main helpers:
createCommunicationResource(...)buildCommunicationBatchMessage(...)addFhirResourceToCommunication(...)addClaimsResourceToCommunication(...)createCommunicationDraft(...)createOutboxJobFromDraft(...)createCommunicationFacade()
Who Should Use This Package
gdc-sdk-node-tsgdc-sdk-front-ts- portal/backend orchestration layers
- frontend/mobile code that needs stable contracts before runtime wiring
If you need HTTP/GW runtime behavior, use gdc-sdk-node-ts or a future runtime
adapter, not this package directly.
Minimal Examples
Consent check
import {
evaluateRequestedAccess,
getMissingPermissions,
type ConsentCoverageRequest,
} from 'gdc-sdk-core-ts';
import {
EXAMPLE_EMAIL_PROFESSIONAL,
EXAMPLE_INDIVIDUAL_DID_WEB,
} from 'gdc-common-utils-ts/examples/consent-access';
import {
HealthcareActorRoles,
HealthcareBasicSections,
HealthcareConsentPurposes,
} from 'gdc-common-utils-ts/constants/healthcare';
const request: ConsentCoverageRequest = {
subject: EXAMPLE_INDIVIDUAL_DID_WEB,
actor: { actorKind: 'professional', email: EXAMPLE_EMAIL_PROFESSIONAL },
actorRole: HealthcareActorRoles.Physician,
purpose: HealthcareConsentPurposes.Treatment,
sections: [HealthcareBasicSections.HistoryOfMedicationUse.claim],
};
const evaluation = await evaluateRequestedAccess(provider, request);
const missing = getMissingPermissions(evaluation);Relationship invitation
import {
createRelationshipChannelInvitationInput,
createRelationshipChannelOtpStartInput,
createRelationshipPinSetInput,
RelationshipAccessActorKinds,
RelationshipEnrollmentChannels,
RelationshipOtpDeliveryChannels,
RelationshipSubjectKinds,
type RelationshipChannelInvitationInput,
type RelationshipChannelOtpStartInput,
type RelationshipPinSetInput,
} from 'gdc-sdk-core-ts';
import {
buildIndividualDidWeb,
HealthcareActorRoles,
HealthcareConsentPurposes,
} from 'gdc-common-utils-ts';
const tenantId = 'acme-id';
const jurisdiction = 'ES';
const sector = 'health-care';
const providerOrganizationDid = subjectProfile.organizationDid;
const subjectLocalId = subjectProfile.subjectId;
const subjectDid = buildIndividualDidWeb({
organizationDidWeb: providerOrganizationDid,
subjectId: subjectLocalId,
});
const emailProfessional = professionalDirectoryEntry.email;
const actorKind = RelationshipAccessActorKinds.Professional;
const actorIdentifier = emailProfessional;
const actorRole = HealthcareActorRoles.Physician;
const deliveryChannel = RelationshipEnrollmentChannels.Phone;
const deliveryTarget = professionalDirectoryEntry.phone;
const purpose = HealthcareConsentPurposes.Treatment;
const phonePinOptional = false;
const invitationInput: RelationshipChannelInvitationInput = {
tenantId,
jurisdiction,
sector,
subjectId: subjectDid,
subjectKind: RelationshipSubjectKinds.Person,
actorKind,
actorIdentifier,
actorRole,
deliveryChannel,
deliveryTarget,
purpose,
relationshipLabel: 'primary-physician',
phonePinOptional,
};
const invitation = createRelationshipChannelInvitationInput(invitationInput);
const invitationId = 'rel-invite-001';
const otpStartInput: RelationshipChannelOtpStartInput = {
invitationId,
deliveryChannel: RelationshipOtpDeliveryChannels.Sms,
locale: 'es-ES',
};
const otpStart = createRelationshipChannelOtpStartInput(otpStartInput);
const challengeId = 'otp-challenge-001';
const pin = '482915';
const pinSetInput: RelationshipPinSetInput = {
invitationId,
challengeId,
channel: deliveryChannel,
pin,
pinConfirmation: pin,
policy: {
minLength: 6,
numericOnly: true,
},
};
const pinSet = createRelationshipPinSetInput(pinSetInput);Where those variables come from:
tenantId,jurisdiction,sectorcome from the selected GW tenant route contextsubjectDidshould be built withbuildIndividualDidWeb(...)from the provider/subject identifiers you already haveactorKind,actorIdentifier,actorRolecome from the invited professional or related persondeliveryChannel,deliveryTargetcome from the chosen channel for enrollmentinvitationId,challengeIdcome from the backend after creating the invitation and starting OTPpincomes from the invitee during channel enrollment
API Index
The canonical contract should live in JSDoc on exported code. This README is the entrypoint, not the exhaustive reference.
Full Public Surface
The following modules define the complete public SDK surface exported by this package:
src/actor-model.ts- types:
ActorKind,Capability,ActorSessionDescriptor,ActorFacadeDescriptor,ActorFlags,ActorSessionDescriptorInput - functions:
filterCapabilitiesForActor(...),expandActorSessionDescriptorToFacades(...),buildActorSessionDescriptorFromActorFlags(...)
- types:
src/bootstrap-facade.ts- types:
BootstrapValidationIssue,OrganizationActivationPayload,BootstrapFacade - function:
createBootstrapFacade()
- types:
src/communication-bundle-contracts.ts- types:
AttachmentObj,CommunicationInput,CommMsgExtendedInput,DateRange,SectionFilter,IncludedResourceType,BundleSearchQuery,CompositionSearchQuery,ProjectedResourceSummary,BundleSearchResult,CommunicationAuditRecord - functions:
assertCommunicationInput(...),assertCommMsgExtendedInput(...),assertBundleSearchQuery(...)
- types:
src/consent-access.ts- types:
PermissionRequestCommunicationInput,PermissionRequestCommunicationLookup,ActiveConsentProvider - functions:
groupConsentsForControllerView(...),evaluateRequestedAccess(...),getMissingPermissions(...),buildPermissionRequestCommunication(...),buildPermissionRequestCommunicationLookupQuery(...)
- types:
src/communication-draft.ts- constant:
CommunicationOutboxStatuses - types:
CommunicationOutboxStatus,CommunicationDraft,CommunicationDraftCreationOptions,OutboxJob,CommunicationOutboxJob,CommunicationOutboxJobOptions - functions:
createCommunicationDraft(...),getCommunicationFromDraft(...),isCommunicationDraftReady(...),addFhirResourceToDraft(...),addClaimsResourceToDraft(...),createOutboxJobFromDraft(...),updateOutboxJobStatus(...)
- constant:
src/communication-document-facade.ts- types:
ResolvedCommunicationDocument,FhirDocumentSection,FhirDocumentFacade - functions:
getDocumentFromCommunication(...),createFhirDocumentFacade(...),createCommunicationFacade()
- types:
src/communication-outbox.ts- types/interfaces:
OutboxQuery,IOutboxRepository - class:
OutboxRepositoryMemory
- types/interfaces:
src/communication-resource-helpers.ts- types:
FhirResourceLike,CommunicationResourceLike,AttachmentEncodingInput,CommunicationCreationOptions,ResourceAttachmentOptions,CommunicationPayloadResolution,ObservationCodeFilter,CommunicationBatchMessageOptions - functions:
createCommunicationResource(...),buildCommunicationBatchMessage(...),addFhirResourceToCommunication(...),addClaimsResourceToCommunication(...),resolveCommunicationPayloads(...),getFirstBundleDocumentFromCommunication(...),getBundleDocumentEntries(...),getBundleDocumentResourcesByType(...),getMedicationClaimsFromCommunicationDocument(...),sortFhirResourcesByDateDescending(...),getObservationsByCodeFromCommunicationDocument(...)
- types:
src/did-resolution-session.ts- functions:
getProviderDidFromSubjectDid(...),resolveDidDocumentServices(...),resolveProviderIdentityForSubject(...)
- functions:
src/discovery-facade.ts- types/interfaces:
DiscoveryResolutionResult,DiscoveryFacade - function:
createStaticDiscoveryFacade(...)
- types/interfaces:
src/identity-model.ts- types:
DidServiceLike,DidDocumentLike,ResolvedServiceEndpointLike,TransportIdentityState,ActorIdentityState,ProviderIdentityState
- types:
src/identity-store.ts- interfaces:
DidDocumentStore,IdentityStore - class:
MemoryIdentityStore
- interfaces:
src/polling-model.ts- types:
SubmitPayload,AsyncPollRequest,SubmitResponse,PollOptions,PollResult,SubmitAndPollResult - function:
resolvePollOptionsFromSeconds(...)
- types:
src/relationship-access.ts- types:
RelationshipEnrollmentChannel,RelationshipSubjectKind,RelationshipAccessActorKind,RelationshipInvitationStatus,RelationshipOtpDeliveryChannel,RelationshipPinKdf,RelationshipChannelInvitationInput,RelationshipChannelInvitationSummary,RelationshipChannelOtpStartInput,RelationshipChannelOtpConfirmInput,RelationshipChannelOtpChallengeSummary,RelationshipPinPolicy,RelationshipPinSetInput,RelationshipPinVerifyInput,RelationshipLocalKeyEnvelope - functions:
createRelationshipChannelInvitationInput(...),createRelationshipChannelInvitationSummary(...),createRelationshipChannelOtpStartInput(...),createRelationshipChannelOtpConfirmInput(...),createRelationshipChannelOtpChallengeSummary(...),createRelationshipPinPolicy(...),createRelationshipPinSetInput(...),createRelationshipPinVerifyInput(...),createRelationshipLocalKeyEnvelope(...)
- types:
src/session-model.ts- types/interfaces:
AppType,AppInfo,DeviceTrustLevel,PersistenceMode,DataPersistencePolicy,InitializeSessionParams,Profile,ProfileRegistryEntry,VaultQueryCondition,VaultQuery,IVaultRepository,IApiConfig,INetwork,IVerifier
- types/interfaces:
src/smart-endpoint-resolver.ts- function:
resolveSmartTokenEndpointForSubject(...)
- function:
src/vital-signs.ts- types:
VitalSignQuantityInput,BloodPressureInput,VitalSignsDocumentBase - functions:
createHeartRateObservation(...),createBodyTemperatureObservation(...),createBloodPressureObservation(...),createVitalSignsFacade(...)
- types:
Actor/session contracts
filterCapabilitiesForActor(...)expandActorSessionDescriptorToFacades(...)buildActorSessionDescriptorFromActorFlags(...)DeviceTrustLevel,PersistenceMode,DataPersistencePolicyMemoryIdentityStore
Identity/discovery/bootstrap
createBootstrapFacade(...)createStaticDiscoveryFacade(...)resolveProviderIdentityForSubject(...)resolveSmartTokenEndpointForSubject(...)gdc-common-utils-ts/docs/101-DATASPACE_DISCOVERY_DEFAULTS.md- shared portal/backend bootstrap guide for
defaults-only,default-first, andinternet-firstdiscovery seeding
- shared portal/backend bootstrap guide for
Discovery boundary rule:
gdc-sdk-core-tsdefines runtime-neutral contracts plus reusable transport-agnostic discovery resolvers that accept injectedfetch- host DSP resolution uses the contextualized hosting-operator entrypoint
/<hosting-operator-network-context>/.well-known/dspace-version - frontend DTO/card mapping belongs to
gdc-sdk-front-ts
Polling helpers
Communication/document contracts
Consent access
groupConsentsForControllerView(...)evaluateRequestedAccess(...)getMissingPermissions(...)buildPermissionRequestCommunication(...)buildPermissionRequestCommunicationLookupQuery(...)
Consent precedence in the shared model:
- explicit deny for a concrete email
- explicit permit for a concrete email
- organization decision
- jurisdiction decision
- default deny
Relationship access
createRelationshipChannelInvitationInput(...)createRelationshipChannelInvitationSummary(...)createRelationshipChannelOtpStartInput(...)createRelationshipChannelOtpConfirmInput(...)createRelationshipChannelOtpChallengeSummary(...)createRelationshipPinPolicy(...)createRelationshipPinSetInput(...)createRelationshipPinVerifyInput(...)createRelationshipLocalKeyEnvelope(...)
Communication/document builders and readers
createCommunicationResource(...)buildCommunicationBatchMessage(...)addFhirResourceToCommunication(...)addClaimsResourceToCommunication(...)resolveCommunicationPayloads(...)getFirstBundleDocumentFromCommunication(...)getBundleDocumentEntries(...)getBundleDocumentResourcesByType(...)getMedicationClaimsFromCommunicationDocument(...)sortFhirResourcesByDateDescending(...)getObservationsByCodeFromCommunicationDocument(...)
Drafts and outbox
createCommunicationDraft(...)getCommunicationFromDraft(...)isCommunicationDraftReady(...)addFhirResourceToDraft(...)addClaimsResourceToDraft(...)createOutboxJobFromDraft(...)updateOutboxJobStatus(...)OutboxJobCommunicationOutboxJobIOutboxRepositoryOutboxRepositoryMemory
IPS search through Communication
For IPS document requests, the frontend/web app should create a FHIR
Communication whose Communication.content-reference contains the relative
FHIR search path for the index service.
Employee Contract
Employee lifecycle, search semantics, and the canonical EmployeeDraft
contract live in docs/101-EMPLOYEES.md.
The shared bundle/editor mechanics for employee live in:
Communication.content-referencestores what must be searched, for example the relativeBundlequery pathCommunication.recipientis the logical/clinical conversation recipient, not the HTTP endpointDIDComm
to/audbelong to the transport envelope or runtime submitter, not toCommunication.content-reference
Typical flow:
- build
summaryOperationRequestParameters - flatten them to
summaryOperationRequestReferencePath - create
Communicationclaims withcommunication.newIpsSummarySearchCommunication(...) - place the
Communicationin a draft - freeze the draft into an outbox job
- let the runtime/backend resolve the provider and send the envelope
See the executable example:
High-level document facade
Vital signs
createHeartRateObservation(...)createBodyTemperatureObservation(...)createBloodPressureObservation(...)createVitalSignsFacade(...)
Documentation Rule
- JSDoc on exported code is canonical.
- README should explain the business flows first.
- Runtime routing details belong in node/front runtime docs, not in this package.
