gdc-common-utils-ts 2.0.16 → 2.0.18

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 (29) hide show
  1. package/dist/constants/verifiable-credentials.d.ts +7 -0
  2. package/dist/constants/verifiable-credentials.js +7 -0
  3. package/dist/examples/contract-examples.d.ts +1 -0
  4. package/dist/examples/contract-examples.js +1 -0
  5. package/dist/examples/index.d.ts +1 -0
  6. package/dist/examples/index.js +1 -0
  7. package/dist/examples/inter-tenant-access-contract.d.ts +124 -0
  8. package/dist/examples/inter-tenant-access-contract.js +134 -0
  9. package/dist/examples/shared.d.ts +5 -0
  10. package/dist/examples/shared.js +5 -0
  11. package/dist/models/index.d.ts +1 -0
  12. package/dist/models/index.js +1 -0
  13. package/dist/models/inter-tenant-access-contract.d.ts +105 -0
  14. package/dist/models/inter-tenant-access-contract.js +78 -0
  15. package/dist/utils/bundle-reader.d.ts +19 -0
  16. package/dist/utils/bundle-reader.js +43 -0
  17. package/dist/utils/evidence-blockchain-references.d.ts +2 -0
  18. package/dist/utils/evidence-blockchain-references.js +4 -0
  19. package/dist/utils/gw-core-commercial-contract.d.ts +41 -0
  20. package/dist/utils/gw-core-commercial-contract.js +71 -0
  21. package/dist/utils/index.d.ts +4 -0
  22. package/dist/utils/index.js +4 -0
  23. package/dist/utils/inter-tenant-access-contract.d.ts +44 -0
  24. package/dist/utils/inter-tenant-access-contract.js +358 -0
  25. package/dist/utils/legal-organization-verification-result.d.ts +37 -0
  26. package/dist/utils/legal-organization-verification-result.js +106 -0
  27. package/dist/utils/organization-authorization-urn.d.ts +43 -0
  28. package/dist/utils/organization-authorization-urn.js +87 -0
  29. package/package.json +1 -1
@@ -36,5 +36,12 @@ export declare const ActivationCredentialTypes: Readonly<{
36
36
  export declare const ProfessionalCredentialTypes: Readonly<{
37
37
  EmployeeCredential: "EmployeeCredential";
38
38
  }>;
39
+ /**
40
+ * Canonical credential subtype names used by inter-tenant authorization
41
+ * contracts for cross-organization access.
42
+ */
43
+ export declare const ContractCredentialTypes: Readonly<{
44
+ InterTenantAccessContractCredential: "InterTenantAccessContractCredential";
45
+ }>;
39
46
  export declare const ORGANIZATION_ACTIVATION_VC_TYPES: readonly ("OrganizationCredential" | "LegalOrganizationCredential")[];
40
47
  export declare const REPRESENTATIVE_ACTIVATION_VC_TYPES: readonly ("LegalRepresentativeCredential" | "PersonCredential")[];
@@ -38,6 +38,13 @@ export const ActivationCredentialTypes = Object.freeze({
38
38
  export const ProfessionalCredentialTypes = Object.freeze({
39
39
  EmployeeCredential: 'EmployeeCredential',
40
40
  });
41
+ /**
42
+ * Canonical credential subtype names used by inter-tenant authorization
43
+ * contracts for cross-organization access.
44
+ */
45
+ export const ContractCredentialTypes = Object.freeze({
46
+ InterTenantAccessContractCredential: 'InterTenantAccessContractCredential',
47
+ });
41
48
  export const ORGANIZATION_ACTIVATION_VC_TYPES = Object.freeze([
42
49
  ActivationCredentialTypes.OrganizationCredential,
43
50
  ActivationCredentialTypes.LegalOrganizationCredential,
@@ -8,6 +8,7 @@
8
8
  export * from './shared';
9
9
  export * from './ica-activation-proof';
10
10
  export * from './organization-controller';
11
+ export * from './inter-tenant-access-contract';
11
12
  export * from './individual-controller';
12
13
  export * from './professional';
13
14
  export * from './related-person';
@@ -9,6 +9,7 @@
9
9
  export * from './shared.js';
10
10
  export * from './ica-activation-proof.js';
11
11
  export * from './organization-controller.js';
12
+ export * from './inter-tenant-access-contract.js';
12
13
  export * from './individual-controller.js';
13
14
  export * from './professional.js';
14
15
  export * from './related-person.js';
@@ -10,6 +10,7 @@ export * from './professional';
10
10
  export * from './employee';
11
11
  export * from './license';
12
12
  export * from './invoice';
13
+ export * from './inter-tenant-access-contract';
13
14
  export * from './related-person';
14
15
  export * from './consent-access';
15
16
  export * from './relationship-access';
@@ -10,6 +10,7 @@ export * from './professional.js';
10
10
  export * from './employee.js';
11
11
  export * from './license.js';
12
12
  export * from './invoice.js';
13
+ export * from './inter-tenant-access-contract.js';
13
14
  export * from './related-person.js';
14
15
  export * from './consent-access.js';
15
16
  export * from './relationship-access.js';
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Shared synthetic inter-tenant contract fixtures reused by GW and SDK tests.
3
+ *
4
+ * Scenario:
5
+ * - `acme-id` is the clinical provider tenant in `health-care`
6
+ * - `lab-id` is the research tenant in `health-research`
7
+ * - both are assumed to be hosted by the same operator for the current scope
8
+ *
9
+ * Programmer hints:
10
+ * - provider = the tenant that owns/exposes the data
11
+ * - consumer = the foreign tenant asking for access
12
+ * - capability = the allowed technical scope, for example
13
+ * `organization/Composition.rs`
14
+ * - purpose = the allowed business/legal reason, for example `RESEARCH`
15
+ * - instantiates-uri = primary agreement artifact URL/CID, typically the
16
+ * signed PDF of the contract itself
17
+ * - invoice/payment evidence is intentionally not modeled as a mandatory core
18
+ * field in this first inter-tenant fixture
19
+ */
20
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_ID: "urn:uuid:inter-tenant-access-contract-001";
21
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_FROM: "2026-06-29T00:00:00.000Z";
22
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_UNTIL: "2027-06-29T00:00:00.000Z";
23
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_PURPOSE: "RESEARCH";
24
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SCOPE: "organization/Composition.rs";
25
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SUBJECT_DID: "did:web:api.acme.org:individual:123";
26
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SECTION: "LOINC|48765-2";
27
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_AGREEMENT_PDF_URL: "https://portal.example.org/files/contracts/inter-tenant-contract-acme-lab-001.pdf";
28
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_PROFESSIONAL_DID: "did:web:api.lab.org:employee:researcher1@lab.org:ISCO-08|2211";
29
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SMART_SCOPE: "organization/Composition.rs?subject=did:web:api.acme.org:individual:123&section=LOINC|48765-2";
30
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CLAIMS: Readonly<{
31
+ readonly "Contract.identifier": "urn:uuid:inter-tenant-access-contract-001";
32
+ readonly "Contract.status": "executed";
33
+ readonly "Contract.issued": "2026-06-29T00:00:00.000Z";
34
+ readonly "Contract.applies-start": "2026-06-29T00:00:00.000Z";
35
+ readonly "Contract.applies-end": "2027-06-29T00:00:00.000Z";
36
+ readonly "Contract.provider-organization": "did:web:api.acme.org";
37
+ readonly "Contract.consumer-organization": "did:web:api.lab.org";
38
+ readonly "Contract.provider-controller": "did:web:people.acme.org:controllers:primary";
39
+ readonly "Contract.consumer-controller": "did:web:people.lab.org:controllers:primary";
40
+ readonly "Contract.security-label": "organization/Composition.rs";
41
+ readonly "Contract.term-type": "RESEARCH";
42
+ readonly "Contract.instantiates-uri": "https://portal.example.org/files/contracts/inter-tenant-contract-acme-lab-001.pdf";
43
+ }>;
44
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_RESOURCE: Readonly<{
45
+ [x: string]: any;
46
+ }>;
47
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CREDENTIAL: Readonly<import("..").VerifiableCredentialV2>;
48
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT: Readonly<{
49
+ readonly providerTenantId: "acme-id";
50
+ readonly providerSector: "health-care";
51
+ readonly providerOrganizationDid: "did:web:api.acme.org";
52
+ readonly consumerTenantId: "lab-id";
53
+ readonly consumerSector: "health-research";
54
+ readonly consumerOrganizationDid: "did:web:api.lab.org";
55
+ readonly jurisdiction: "ES";
56
+ readonly actorRole: "ISCO-08|2211";
57
+ readonly subjectDid: "did:web:api.acme.org:individual:123";
58
+ readonly consumerProfessionalDid: "did:web:api.lab.org:employee:researcher1@lab.org:ISCO-08|2211";
59
+ readonly requestedScope: "organization/Composition.rs";
60
+ readonly requestedSection: "LOINC|48765-2";
61
+ readonly smartScope: "organization/Composition.rs?subject=did:web:api.acme.org:individual:123&section=LOINC|48765-2";
62
+ readonly purpose: "RESEARCH";
63
+ }>;
64
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_PROVIDER_ORGANIZATION_URN: string;
65
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_ORGANIZATION_URN: string;
66
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_MEMBER_URN: string;
67
+ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT_WITH_URNS: Readonly<{
68
+ readonly providerOrganizationUrn: string;
69
+ readonly consumerOrganizationUrn: string;
70
+ readonly consumerMemberUrn: string;
71
+ readonly providerTenantId: "acme-id";
72
+ readonly providerSector: "health-care";
73
+ readonly providerOrganizationDid: "did:web:api.acme.org";
74
+ readonly consumerTenantId: "lab-id";
75
+ readonly consumerSector: "health-research";
76
+ readonly consumerOrganizationDid: "did:web:api.lab.org";
77
+ readonly jurisdiction: "ES";
78
+ readonly actorRole: "ISCO-08|2211";
79
+ readonly subjectDid: "did:web:api.acme.org:individual:123";
80
+ readonly consumerProfessionalDid: "did:web:api.lab.org:employee:researcher1@lab.org:ISCO-08|2211";
81
+ readonly requestedScope: "organization/Composition.rs";
82
+ readonly requestedSection: "LOINC|48765-2";
83
+ readonly smartScope: "organization/Composition.rs?subject=did:web:api.acme.org:individual:123&section=LOINC|48765-2";
84
+ readonly purpose: "RESEARCH";
85
+ }>;
86
+ /**
87
+ * Consent-style organization-to-employee delegation rule reused for the
88
+ * consumer tenant side.
89
+ *
90
+ * This intentionally reuses the existing `Consent.*` rule pattern:
91
+ * - `Consent.subject` is the consumer organization URN
92
+ * - `Consent.actor-identifier` is the delegated member URN
93
+ * - `Consent.actor-role` carries the role separately
94
+ * - `Consent.source-reference` points to the blockchain-safe contract VC
95
+ * reference that was or will be anchored on-chain
96
+ */
97
+ export declare const EXAMPLE_INTER_TENANT_EMPLOYEE_CONTRACT_AUTHORIZATION_CONSENT: Readonly<{
98
+ readonly '@context': "org.hl7.fhir.api";
99
+ readonly "Consent.identifier": "urn:uuid:employee-contract-authorization-001";
100
+ readonly "Consent.subject": string;
101
+ readonly "Consent.actor-identifier": string;
102
+ readonly "Consent.actor-role": "ISCO-08|2211";
103
+ readonly "Consent.decision": "permit";
104
+ readonly "Consent.purpose": "RESEARCH";
105
+ readonly "Consent.action": "organization/Composition.rs";
106
+ readonly "Consent.source-reference": string | undefined;
107
+ readonly "Consent.date": "2026-06-29T00:00:00.000Z";
108
+ readonly "Consent.period-start": "2026-06-29T00:00:00.000Z";
109
+ readonly "Consent.period-end": "2027-06-29T00:00:00.000Z";
110
+ }>;
111
+ export declare const EXAMPLE_INTER_TENANT_PROVIDER_CONTRACT_AUTHORIZATION_CONSENT: Readonly<{
112
+ readonly '@context': "org.hl7.fhir.api";
113
+ readonly "Consent.identifier": "urn:uuid:provider-contract-authorization-001";
114
+ readonly "Consent.subject": string;
115
+ readonly "Consent.actor-identifier": string;
116
+ readonly "Consent.actor-role": "organization";
117
+ readonly "Consent.decision": "permit";
118
+ readonly "Consent.purpose": "RESEARCH";
119
+ readonly "Consent.action": "organization/Composition.rs";
120
+ readonly "Consent.source-reference": string | undefined;
121
+ readonly "Consent.date": "2026-06-29T00:00:00.000Z";
122
+ readonly "Consent.period-start": "2026-06-29T00:00:00.000Z";
123
+ readonly "Consent.period-end": "2027-06-29T00:00:00.000Z";
124
+ }>;
@@ -0,0 +1,134 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ import { ServiceCapability } from '../constants/service-capabilities.js';
3
+ import { DataspaceSectors } from '../constants/sectors.js';
4
+ import { ClaimConsent } from '../models/consent-rule.js';
5
+ import { ClaimInterTenantAccessContract } from '../models/inter-tenant-access-contract.js';
6
+ import { buildInterTenantAccessContractCredential, buildInterTenantAccessContractResource, getInterTenantAccessContractBlockchainReference, } from '../utils/inter-tenant-access-contract.js';
7
+ import { buildMemberAuthorizationUrn, buildOrganizationAuthorizationUrn, } from '../utils/organization-authorization-urn.js';
8
+ import { EXAMPLE_API_ORGANIZATION_DID, EXAMPLE_CONTROLLER_DID, EXAMPLE_HEALTHCARE_ACTOR_ROLE_PHYSICIAN, EXAMPLE_JURISDICTION, EXAMPLE_RESEARCH_API_ORGANIZATION_DID, EXAMPLE_RESEARCH_CONTROLLER_DID, EXAMPLE_RESEARCH_TENANT_IDENTIFIER, EXAMPLE_SECTOR, EXAMPLE_TENANT_IDENTIFIER, } from './shared.js';
9
+ /**
10
+ * Shared synthetic inter-tenant contract fixtures reused by GW and SDK tests.
11
+ *
12
+ * Scenario:
13
+ * - `acme-id` is the clinical provider tenant in `health-care`
14
+ * - `lab-id` is the research tenant in `health-research`
15
+ * - both are assumed to be hosted by the same operator for the current scope
16
+ *
17
+ * Programmer hints:
18
+ * - provider = the tenant that owns/exposes the data
19
+ * - consumer = the foreign tenant asking for access
20
+ * - capability = the allowed technical scope, for example
21
+ * `organization/Composition.rs`
22
+ * - purpose = the allowed business/legal reason, for example `RESEARCH`
23
+ * - instantiates-uri = primary agreement artifact URL/CID, typically the
24
+ * signed PDF of the contract itself
25
+ * - invoice/payment evidence is intentionally not modeled as a mandatory core
26
+ * field in this first inter-tenant fixture
27
+ */
28
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_ID = 'urn:uuid:inter-tenant-access-contract-001';
29
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_FROM = '2026-06-29T00:00:00.000Z';
30
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_UNTIL = '2027-06-29T00:00:00.000Z';
31
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_PURPOSE = 'RESEARCH';
32
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SCOPE = ServiceCapability.IndexReader;
33
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SUBJECT_DID = 'did:web:api.acme.org:individual:123';
34
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SECTION = 'LOINC|48765-2';
35
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_AGREEMENT_PDF_URL = 'https://portal.example.org/files/contracts/inter-tenant-contract-acme-lab-001.pdf';
36
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_PROFESSIONAL_DID = `${EXAMPLE_RESEARCH_API_ORGANIZATION_DID}:employee:researcher1@lab.org:${EXAMPLE_HEALTHCARE_ACTOR_ROLE_PHYSICIAN}`;
37
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SMART_SCOPE = `${EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SCOPE}?subject=${EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SUBJECT_DID}&section=${EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SECTION}`;
38
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CLAIMS = Object.freeze({
39
+ [ClaimInterTenantAccessContract.identifier]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_ID,
40
+ [ClaimInterTenantAccessContract.status]: 'executed',
41
+ [ClaimInterTenantAccessContract.issued]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_FROM,
42
+ [ClaimInterTenantAccessContract.appliesStart]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_FROM,
43
+ [ClaimInterTenantAccessContract.appliesEnd]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_UNTIL,
44
+ [ClaimInterTenantAccessContract.providerOrganization]: EXAMPLE_API_ORGANIZATION_DID,
45
+ [ClaimInterTenantAccessContract.consumerOrganization]: EXAMPLE_RESEARCH_API_ORGANIZATION_DID,
46
+ [ClaimInterTenantAccessContract.providerController]: EXAMPLE_CONTROLLER_DID,
47
+ [ClaimInterTenantAccessContract.consumerController]: EXAMPLE_RESEARCH_CONTROLLER_DID,
48
+ [ClaimInterTenantAccessContract.capability]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SCOPE,
49
+ [ClaimInterTenantAccessContract.purpose]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_PURPOSE,
50
+ [ClaimInterTenantAccessContract.instantiatesUri]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_AGREEMENT_PDF_URL,
51
+ });
52
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_RESOURCE = Object.freeze(buildInterTenantAccessContractResource(EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CLAIMS));
53
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CREDENTIAL = Object.freeze(buildInterTenantAccessContractCredential({
54
+ claims: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CLAIMS,
55
+ issuer: EXAMPLE_CONTROLLER_DID,
56
+ validFrom: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_FROM,
57
+ validUntil: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_UNTIL,
58
+ additionalCredential: {
59
+ id: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_ID,
60
+ },
61
+ }));
62
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT = Object.freeze({
63
+ providerTenantId: EXAMPLE_TENANT_IDENTIFIER,
64
+ providerSector: EXAMPLE_SECTOR,
65
+ providerOrganizationDid: EXAMPLE_API_ORGANIZATION_DID,
66
+ consumerTenantId: EXAMPLE_RESEARCH_TENANT_IDENTIFIER,
67
+ consumerSector: DataspaceSectors.HealthResearch,
68
+ consumerOrganizationDid: EXAMPLE_RESEARCH_API_ORGANIZATION_DID,
69
+ jurisdiction: EXAMPLE_JURISDICTION,
70
+ actorRole: EXAMPLE_HEALTHCARE_ACTOR_ROLE_PHYSICIAN,
71
+ subjectDid: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SUBJECT_DID,
72
+ consumerProfessionalDid: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_PROFESSIONAL_DID,
73
+ requestedScope: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SCOPE,
74
+ requestedSection: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SECTION,
75
+ smartScope: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SMART_SCOPE,
76
+ purpose: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_PURPOSE,
77
+ });
78
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_PROVIDER_ORGANIZATION_URN = buildOrganizationAuthorizationUrn({
79
+ identifierType: 'TAX',
80
+ identifierValue: EXAMPLE_TENANT_IDENTIFIER,
81
+ });
82
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_ORGANIZATION_URN = buildOrganizationAuthorizationUrn({
83
+ identifierType: 'TAX',
84
+ identifierValue: EXAMPLE_RESEARCH_TENANT_IDENTIFIER,
85
+ });
86
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_MEMBER_URN = buildMemberAuthorizationUrn({
87
+ organizationUrn: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_ORGANIZATION_URN,
88
+ memberId: 'researcher-001',
89
+ });
90
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT_WITH_URNS = Object.freeze({
91
+ ...EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT,
92
+ providerOrganizationUrn: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_PROVIDER_ORGANIZATION_URN,
93
+ consumerOrganizationUrn: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_ORGANIZATION_URN,
94
+ consumerMemberUrn: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_MEMBER_URN,
95
+ });
96
+ /**
97
+ * Consent-style organization-to-employee delegation rule reused for the
98
+ * consumer tenant side.
99
+ *
100
+ * This intentionally reuses the existing `Consent.*` rule pattern:
101
+ * - `Consent.subject` is the consumer organization URN
102
+ * - `Consent.actor-identifier` is the delegated member URN
103
+ * - `Consent.actor-role` carries the role separately
104
+ * - `Consent.source-reference` points to the blockchain-safe contract VC
105
+ * reference that was or will be anchored on-chain
106
+ */
107
+ export const EXAMPLE_INTER_TENANT_EMPLOYEE_CONTRACT_AUTHORIZATION_CONSENT = Object.freeze({
108
+ '@context': 'org.hl7.fhir.api',
109
+ [ClaimConsent.identifier]: 'urn:uuid:employee-contract-authorization-001',
110
+ [ClaimConsent.subject]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_ORGANIZATION_URN,
111
+ [ClaimConsent.actorIdentifier]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_MEMBER_URN,
112
+ [ClaimConsent.actorRole]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT.actorRole,
113
+ [ClaimConsent.decision]: 'permit',
114
+ [ClaimConsent.purpose]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT.purpose,
115
+ [ClaimConsent.action]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT.requestedScope,
116
+ [ClaimConsent.sourceReference]: getInterTenantAccessContractBlockchainReference(EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CREDENTIAL),
117
+ [ClaimConsent.date]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_FROM,
118
+ [ClaimConsent.periodStart]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_FROM,
119
+ [ClaimConsent.periodEnd]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_UNTIL,
120
+ });
121
+ export const EXAMPLE_INTER_TENANT_PROVIDER_CONTRACT_AUTHORIZATION_CONSENT = Object.freeze({
122
+ '@context': 'org.hl7.fhir.api',
123
+ [ClaimConsent.identifier]: 'urn:uuid:provider-contract-authorization-001',
124
+ [ClaimConsent.subject]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_PROVIDER_ORGANIZATION_URN,
125
+ [ClaimConsent.actorIdentifier]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_ORGANIZATION_URN,
126
+ [ClaimConsent.actorRole]: 'organization',
127
+ [ClaimConsent.decision]: 'permit',
128
+ [ClaimConsent.purpose]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT.purpose,
129
+ [ClaimConsent.action]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT.requestedScope,
130
+ [ClaimConsent.sourceReference]: getInterTenantAccessContractBlockchainReference(EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CREDENTIAL),
131
+ [ClaimConsent.date]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_FROM,
132
+ [ClaimConsent.periodStart]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_FROM,
133
+ [ClaimConsent.periodEnd]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_UNTIL,
134
+ });
@@ -11,12 +11,15 @@ import { IdKind } from '../constants/identity-identifiers';
11
11
  * - all values below are synthetic documentation/test fixtures, never real data
12
12
  */
13
13
  export declare const EXAMPLE_TENANT_IDENTIFIER: "acme-id";
14
+ export declare const EXAMPLE_RESEARCH_TENANT_IDENTIFIER: "lab-id";
14
15
  export declare const EXAMPLE_JURISDICTION: "ES";
15
16
  export declare const EXAMPLE_HOST_COVERAGE_SCOPE: "EU";
16
17
  export declare const EXAMPLE_NETWORK_TYPE: "test";
17
18
  export declare const EXAMPLE_ROUTE_VERSION: "v1";
18
19
  export declare const EXAMPLE_SECTOR: "health-care";
20
+ export declare const EXAMPLE_RESEARCH_SECTOR: "health-research";
19
21
  export declare const EXAMPLE_EMAIL_CONTROLLER_ORG: "controller@acme.org";
22
+ export declare const EXAMPLE_EMAIL_CONTROLLER_RESEARCH_ORG: "controller@lab.org";
20
23
  export declare const EXAMPLE_ORGANIZATION_LEGAL_NAME: "ACME HEALTH SL";
21
24
  export declare const EXAMPLE_LEGAL_ORGANIZATION_TAX_ID: "VATES-B00112233";
22
25
  export declare const EXAMPLE_EMAIL_CONTROLLER_INDIVIDUAL: "ana.parent@example.org";
@@ -101,9 +104,11 @@ export declare const EXAMPLE_HOST_ROUTE_CONTEXT: {
101
104
  readonly sector: "test";
102
105
  };
103
106
  export declare const EXAMPLE_CONTROLLER_DID: "did:web:people.acme.org:controllers:primary";
107
+ export declare const EXAMPLE_RESEARCH_CONTROLLER_DID: "did:web:people.lab.org:controllers:primary";
104
108
  export declare const EXAMPLE_CONTROLLER_EMAIL: "controller@acme.org";
105
109
  export declare const EXAMPLE_CONTROLLER_SAME_AS: "mailto:controller@acme.org";
106
110
  export declare const EXAMPLE_API_ORGANIZATION_DID: "did:web:api.acme.org";
111
+ export declare const EXAMPLE_RESEARCH_API_ORGANIZATION_DID: "did:web:api.lab.org";
107
112
  export declare const EXAMPLE_SERVICE_PUBLIC_DID: "did:web:public.acme.org";
108
113
  export declare const EXAMPLE_PROFESSIONAL_DID: string;
109
114
  export declare const EXAMPLE_PROVIDER_ORGANIZATION_DID: "did:web:hospital.acme.org";
@@ -26,12 +26,15 @@ import { medicationStatementFlatToFhirR4 } from '../utils/clinical-resource-conv
26
26
  * - all values below are synthetic documentation/test fixtures, never real data
27
27
  */
28
28
  export const EXAMPLE_TENANT_IDENTIFIER = 'acme-id';
29
+ export const EXAMPLE_RESEARCH_TENANT_IDENTIFIER = 'lab-id';
29
30
  export const EXAMPLE_JURISDICTION = 'ES';
30
31
  export const EXAMPLE_HOST_COVERAGE_SCOPE = 'EU';
31
32
  export const EXAMPLE_NETWORK_TYPE = HostNetworkTypes.Test;
32
33
  export const EXAMPLE_ROUTE_VERSION = 'v1';
33
34
  export const EXAMPLE_SECTOR = DataspaceSectors.HealthCare;
35
+ export const EXAMPLE_RESEARCH_SECTOR = DataspaceSectors.HealthResearch;
34
36
  export const EXAMPLE_EMAIL_CONTROLLER_ORG = 'controller@acme.org';
37
+ export const EXAMPLE_EMAIL_CONTROLLER_RESEARCH_ORG = 'controller@lab.org';
35
38
  export const EXAMPLE_ORGANIZATION_LEGAL_NAME = 'ACME HEALTH SL';
36
39
  export const EXAMPLE_LEGAL_ORGANIZATION_TAX_ID = 'VATES-B00112233';
37
40
  export const EXAMPLE_EMAIL_CONTROLLER_INDIVIDUAL = 'ana.parent@example.org';
@@ -116,9 +119,11 @@ export const EXAMPLE_HOST_ROUTE_CONTEXT = {
116
119
  sector: EXAMPLE_NETWORK_TYPE,
117
120
  };
118
121
  export const EXAMPLE_CONTROLLER_DID = 'did:web:people.acme.org:controllers:primary';
122
+ export const EXAMPLE_RESEARCH_CONTROLLER_DID = 'did:web:people.lab.org:controllers:primary';
119
123
  export const EXAMPLE_CONTROLLER_EMAIL = EXAMPLE_EMAIL_CONTROLLER_ORG;
120
124
  export const EXAMPLE_CONTROLLER_SAME_AS = `mailto:${EXAMPLE_CONTROLLER_EMAIL}`;
121
125
  export const EXAMPLE_API_ORGANIZATION_DID = 'did:web:api.acme.org';
126
+ export const EXAMPLE_RESEARCH_API_ORGANIZATION_DID = 'did:web:api.lab.org';
122
127
  export const EXAMPLE_SERVICE_PUBLIC_DID = 'did:web:public.acme.org';
123
128
  export const EXAMPLE_PROFESSIONAL_DID = buildProfessionalDidWeb({
124
129
  organizationDidWeb: 'did:web:api.acme.org',
@@ -22,6 +22,7 @@ export * from './interoperable-claims';
22
22
  export * from './indexing';
23
23
  export * from './identity-bootstrap';
24
24
  export * from './individual-onboarding';
25
+ export * from './inter-tenant-access-contract';
25
26
  export * from './issue';
26
27
  export * from './jsonapi';
27
28
  export * from './jwe';
@@ -22,6 +22,7 @@ export * from './interoperable-claims.js';
22
22
  export * from './indexing.js';
23
23
  export * from './identity-bootstrap.js';
24
24
  export * from './individual-onboarding.js';
25
+ export * from './inter-tenant-access-contract.js';
25
26
  export * from './issue.js';
26
27
  export * from './jsonapi.js';
27
28
  export * from './jwe.js';
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Canonical flat claim keys used when a frontend captures an inter-tenant
3
+ * access contract form and sends it to a backend before the final FHIR
4
+ * `Contract` resource is assembled.
5
+ *
6
+ * Notes:
7
+ * - these keys are claims-first transport helpers, not the legal source of
8
+ * truth
9
+ * - the canonical legal payload is the FHIR `Contract` placed in
10
+ * `credentialSubject` of the emitted VC
11
+ * - custom flat keys are used only where base FHIR does not define a simple
12
+ * one-claim scalar path suitable for UI transport
13
+ */
14
+ export declare enum ClaimInterTenantAccessContract {
15
+ /** Stable business identifier of the agreement/contract. */
16
+ identifier = "Contract.identifier",
17
+ /** FHIR Contract lifecycle status, for example `executed` or `amended`. */
18
+ status = "Contract.status",
19
+ /** When the agreement was formally issued. */
20
+ issued = "Contract.issued",
21
+ /** Agreement validity start date/time. */
22
+ appliesStart = "Contract.applies-start",
23
+ /** Agreement validity end date/time. */
24
+ appliesEnd = "Contract.applies-end",
25
+ /**
26
+ * Provider organization DID.
27
+ *
28
+ * Meaning for programmers:
29
+ * - this is the tenant that owns/exposes the protected data
30
+ * - in the current example this is `did:web:api.acme.org`
31
+ */
32
+ providerOrganization = "Contract.provider-organization",
33
+ /**
34
+ * Consumer organization DID.
35
+ *
36
+ * Meaning for programmers:
37
+ * - this is the foreign tenant requesting access under the agreement
38
+ * - in the current example this is `did:web:api.lab.org`
39
+ */
40
+ consumerOrganization = "Contract.consumer-organization",
41
+ /**
42
+ * DID of the controller who signed on behalf of the provider organization.
43
+ */
44
+ providerController = "Contract.provider-controller",
45
+ /**
46
+ * DID of the controller who signed on behalf of the consumer organization.
47
+ */
48
+ consumerController = "Contract.consumer-controller",
49
+ /**
50
+ * Allowed operational capability, expressed with the same vocabulary used by
51
+ * GW service capabilities and SMART-like root scopes.
52
+ *
53
+ * Example:
54
+ * - `organization/Composition.rs`
55
+ */
56
+ capability = "Contract.security-label",
57
+ /**
58
+ * Allowed business/legal purpose for the access.
59
+ *
60
+ * Example:
61
+ * - `RESEARCH`
62
+ */
63
+ purpose = "Contract.term-type",
64
+ /**
65
+ * External instantiated artifact for the agreement, typically the signed PDF
66
+ * or CID/URL of the contract itself plus direct contractual annexes.
67
+ *
68
+ * Canonical FHIR field:
69
+ * - `Contract.instantiatesUri`
70
+ *
71
+ * Flat claim rule in this stack:
72
+ * - use FHIR-style `instantiates-uri` in claims, then map it to
73
+ * `instantiatesUri` in the actual FHIR resource object
74
+ */
75
+ instantiatesUri = "Contract.instantiates-uri"
76
+ }
77
+ export type InterTenantAccessContractClaims = Partial<Record<ClaimInterTenantAccessContract, string>>;
78
+ export type InterTenantAccessContractSummary = Readonly<{
79
+ identifier?: string;
80
+ status?: string;
81
+ issued?: string;
82
+ appliesStart?: string;
83
+ appliesEnd?: string;
84
+ providerOrganizationDid?: string;
85
+ consumerOrganizationDid?: string;
86
+ providerControllerDid?: string;
87
+ consumerControllerDid?: string;
88
+ capabilities: readonly string[];
89
+ purposes: readonly string[];
90
+ }>;
91
+ export type InterTenantAccessContractMatchCriteria = Readonly<{
92
+ providerOrganizationDid: string;
93
+ consumerOrganizationDid: string;
94
+ requiredCapabilities?: readonly string[];
95
+ purpose?: string;
96
+ now?: string | Date;
97
+ }>;
98
+ export type InterTenantContractAuthorizationConsentCriteria = Readonly<{
99
+ consumerOrganizationDid: string;
100
+ actorIdentifier: string;
101
+ actorRole?: string;
102
+ requiredCapabilities?: readonly string[];
103
+ purpose?: string;
104
+ now?: string | Date;
105
+ }>;
@@ -0,0 +1,78 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ /**
3
+ * Canonical flat claim keys used when a frontend captures an inter-tenant
4
+ * access contract form and sends it to a backend before the final FHIR
5
+ * `Contract` resource is assembled.
6
+ *
7
+ * Notes:
8
+ * - these keys are claims-first transport helpers, not the legal source of
9
+ * truth
10
+ * - the canonical legal payload is the FHIR `Contract` placed in
11
+ * `credentialSubject` of the emitted VC
12
+ * - custom flat keys are used only where base FHIR does not define a simple
13
+ * one-claim scalar path suitable for UI transport
14
+ */
15
+ export var ClaimInterTenantAccessContract;
16
+ (function (ClaimInterTenantAccessContract) {
17
+ /** Stable business identifier of the agreement/contract. */
18
+ ClaimInterTenantAccessContract["identifier"] = "Contract.identifier";
19
+ /** FHIR Contract lifecycle status, for example `executed` or `amended`. */
20
+ ClaimInterTenantAccessContract["status"] = "Contract.status";
21
+ /** When the agreement was formally issued. */
22
+ ClaimInterTenantAccessContract["issued"] = "Contract.issued";
23
+ /** Agreement validity start date/time. */
24
+ ClaimInterTenantAccessContract["appliesStart"] = "Contract.applies-start";
25
+ /** Agreement validity end date/time. */
26
+ ClaimInterTenantAccessContract["appliesEnd"] = "Contract.applies-end";
27
+ /**
28
+ * Provider organization DID.
29
+ *
30
+ * Meaning for programmers:
31
+ * - this is the tenant that owns/exposes the protected data
32
+ * - in the current example this is `did:web:api.acme.org`
33
+ */
34
+ ClaimInterTenantAccessContract["providerOrganization"] = "Contract.provider-organization";
35
+ /**
36
+ * Consumer organization DID.
37
+ *
38
+ * Meaning for programmers:
39
+ * - this is the foreign tenant requesting access under the agreement
40
+ * - in the current example this is `did:web:api.lab.org`
41
+ */
42
+ ClaimInterTenantAccessContract["consumerOrganization"] = "Contract.consumer-organization";
43
+ /**
44
+ * DID of the controller who signed on behalf of the provider organization.
45
+ */
46
+ ClaimInterTenantAccessContract["providerController"] = "Contract.provider-controller";
47
+ /**
48
+ * DID of the controller who signed on behalf of the consumer organization.
49
+ */
50
+ ClaimInterTenantAccessContract["consumerController"] = "Contract.consumer-controller";
51
+ /**
52
+ * Allowed operational capability, expressed with the same vocabulary used by
53
+ * GW service capabilities and SMART-like root scopes.
54
+ *
55
+ * Example:
56
+ * - `organization/Composition.rs`
57
+ */
58
+ ClaimInterTenantAccessContract["capability"] = "Contract.security-label";
59
+ /**
60
+ * Allowed business/legal purpose for the access.
61
+ *
62
+ * Example:
63
+ * - `RESEARCH`
64
+ */
65
+ ClaimInterTenantAccessContract["purpose"] = "Contract.term-type";
66
+ /**
67
+ * External instantiated artifact for the agreement, typically the signed PDF
68
+ * or CID/URL of the contract itself plus direct contractual annexes.
69
+ *
70
+ * Canonical FHIR field:
71
+ * - `Contract.instantiatesUri`
72
+ *
73
+ * Flat claim rule in this stack:
74
+ * - use FHIR-style `instantiates-uri` in claims, then map it to
75
+ * `instantiatesUri` in the actual FHIR resource object
76
+ */
77
+ ClaimInterTenantAccessContract["instantiatesUri"] = "Contract.instantiates-uri";
78
+ })(ClaimInterTenantAccessContract || (ClaimInterTenantAccessContract = {}));
@@ -29,6 +29,21 @@ export type BundleReaderResponseAnalysis = Readonly<{
29
29
  success: BundleReaderSeverityBucket;
30
30
  }>;
31
31
  }>;
32
+ /**
33
+ * Returns the canonical claims view for one bundle entry array index.
34
+ *
35
+ * The helper accepts the full bundle-like object plus the entry position to
36
+ * inspect inside `bundle.data[]` or `bundle.entry[]`.
37
+ */
38
+ export declare function getClaimsInBundleEntryAt(bundle: unknown, index: number): Record<string, unknown>;
39
+ /**
40
+ * Returns the merged claims view for the first `data[]` or `entry[]` item in a
41
+ * bundle-like body.
42
+ *
43
+ * Use this for the common "one operation, one returned entry" flows when the
44
+ * caller does not want to manually navigate `body.data[0]`.
45
+ */
46
+ export declare function getClaimsInFirstDataEntry(bundle: unknown): Record<string, unknown>;
32
47
  /**
33
48
  * Runtime-neutral reader for built or received FHIR-like bundles.
34
49
  *
@@ -49,6 +64,10 @@ export declare class BundleReader {
49
64
  openEntry(index: number): this;
50
65
  /** Returns the resolved identifier for one entry array index when present. */
51
66
  getEntryIdentifierByArrayIndex(index: number): string | undefined;
67
+ /** Returns merged claims for one entry array index. */
68
+ getEntryClaimsByArrayIndex(index: number): Record<string, unknown>;
69
+ /** Returns merged claims for the currently opened entry. */
70
+ getActiveEntryClaims(): Record<string, unknown>;
52
71
  /** Returns the first entry array index whose resolved identifier matches the requested value. */
53
72
  getEntryIndexByIdentifier(identifier: string): number | undefined;
54
73
  /** Returns the active entry response status when present. */