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
@@ -0,0 +1,37 @@
1
+ export type LegalOrganizationVerificationCredential = Record<string, unknown>;
2
+ export type LegalOrganizationVerificationCredentialPair = Readonly<{
3
+ verificationEntries: readonly unknown[];
4
+ organizationCredential: LegalOrganizationVerificationCredential;
5
+ legalRepresentativeCredential: LegalOrganizationVerificationCredential;
6
+ }>;
7
+ /**
8
+ * Returns the ICA verification entries currently projected by GW host
9
+ * legal-organization `_transaction`.
10
+ *
11
+ * Supported shapes:
12
+ * - direct `vc[]` projection on the first response entry
13
+ * - nested `resource.icaResponse.body.data[]`
14
+ * - direct ICA `_verify-response` bodies reused in tests/docs
15
+ */
16
+ export declare function getLegalOrganizationVerificationEntriesFromResponseBody(responseBody: unknown): unknown[];
17
+ /**
18
+ * Reads the organization and legal-representative credentials returned by the
19
+ * legal-organization verification flow.
20
+ */
21
+ export declare function readLegalOrganizationVerificationCredentialPairFromResponseBody(responseBody: unknown): LegalOrganizationVerificationCredentialPair;
22
+ /**
23
+ * Reads the canonical organization tax id from the verification credential
24
+ * pair and enforces agreement between organization and representative VC when
25
+ * both values are present.
26
+ */
27
+ export declare function readLegalOrganizationVerificationTaxIdFromResponseBody(responseBody: unknown): string;
28
+ /**
29
+ * Reads `credentialSubject.sameAs` from the legal-representative credential
30
+ * when present.
31
+ */
32
+ export declare function readLegalRepresentativeSameAsFromResponseBody(responseBody: unknown): string | undefined;
33
+ /**
34
+ * Reads `credentialSubject.hasCredential.material` continuity data from the
35
+ * legal-representative credential when present.
36
+ */
37
+ export declare function readLegalRepresentativeBindingFromResponseBody(responseBody: unknown): string | undefined;
@@ -0,0 +1,106 @@
1
+ import { extractCredentialSubject, extractOrganizationTaxId, extractRepresentativeCredentialBinding, extractRepresentativeMemberOfTaxId, } from './activation-policy.js';
2
+ function asObject(value) {
3
+ if (!value || typeof value !== 'object')
4
+ return undefined;
5
+ return value;
6
+ }
7
+ function asArray(value) {
8
+ return Array.isArray(value) ? value : [];
9
+ }
10
+ function findCredentialResource(entries, expectedTypeFragment, fallbackIndex) {
11
+ const byType = entries.find((entry) => {
12
+ const candidate = asObject(entry);
13
+ const typeValue = candidate?.type;
14
+ const tokens = Array.isArray(typeValue)
15
+ ? typeValue.map((token) => String(token || ''))
16
+ : [String(typeValue || '')];
17
+ return tokens.some((token) => token.includes(expectedTypeFragment));
18
+ });
19
+ const selected = asObject(byType) || asObject(entries[fallbackIndex]);
20
+ const resource = asObject(selected?.resource) || selected;
21
+ if (!resource) {
22
+ throw new Error(`Missing '${expectedTypeFragment}' verification credential in legal-organization verification response.`);
23
+ }
24
+ return resource;
25
+ }
26
+ /**
27
+ * Returns the ICA verification entries currently projected by GW host
28
+ * legal-organization `_transaction`.
29
+ *
30
+ * Supported shapes:
31
+ * - direct `vc[]` projection on the first response entry
32
+ * - nested `resource.icaResponse.body.data[]`
33
+ * - direct ICA `_verify-response` bodies reused in tests/docs
34
+ */
35
+ export function getLegalOrganizationVerificationEntriesFromResponseBody(responseBody) {
36
+ const root = asObject(responseBody) || {};
37
+ const topLevelEntries = asArray(root.data);
38
+ const bodyEntries = asArray(asObject(root.body)?.data);
39
+ const firstEntry = asObject(bodyEntries[0]) || asObject(topLevelEntries[0]) || {};
40
+ const projectedCredentials = asArray(firstEntry.vc);
41
+ if (projectedCredentials.length >= 2) {
42
+ return projectedCredentials;
43
+ }
44
+ const nestedIcaResponse = asObject(asObject(firstEntry.resource)?.icaResponse) || {};
45
+ const nestedBodyEntries = asArray(asObject(nestedIcaResponse.body)?.data);
46
+ if (nestedBodyEntries.length >= 2) {
47
+ return nestedBodyEntries;
48
+ }
49
+ const nestedTopLevelEntries = asArray(nestedIcaResponse.data);
50
+ if (nestedTopLevelEntries.length >= 2) {
51
+ return nestedTopLevelEntries;
52
+ }
53
+ if (bodyEntries.length >= 2) {
54
+ return bodyEntries;
55
+ }
56
+ if (topLevelEntries.length >= 2) {
57
+ return topLevelEntries;
58
+ }
59
+ throw new Error('Legal-organization verification response is missing ICA verification credential entries.');
60
+ }
61
+ /**
62
+ * Reads the organization and legal-representative credentials returned by the
63
+ * legal-organization verification flow.
64
+ */
65
+ export function readLegalOrganizationVerificationCredentialPairFromResponseBody(responseBody) {
66
+ const verificationEntries = getLegalOrganizationVerificationEntriesFromResponseBody(responseBody);
67
+ return {
68
+ verificationEntries,
69
+ organizationCredential: findCredentialResource(verificationEntries, 'Organization', 0),
70
+ legalRepresentativeCredential: findCredentialResource(verificationEntries, 'LegalRepresentative', 1),
71
+ };
72
+ }
73
+ /**
74
+ * Reads the canonical organization tax id from the verification credential
75
+ * pair and enforces agreement between organization and representative VC when
76
+ * both values are present.
77
+ */
78
+ export function readLegalOrganizationVerificationTaxIdFromResponseBody(responseBody) {
79
+ const pair = readLegalOrganizationVerificationCredentialPairFromResponseBody(responseBody);
80
+ const organizationTaxId = extractOrganizationTaxId(pair.organizationCredential);
81
+ const representativeTaxId = extractRepresentativeMemberOfTaxId(pair.legalRepresentativeCredential);
82
+ const resolvedTaxId = organizationTaxId || representativeTaxId;
83
+ if (!resolvedTaxId) {
84
+ throw new Error('Legal-organization verification response is missing organization tax id in both organization and representative credentials.');
85
+ }
86
+ if (organizationTaxId && representativeTaxId && organizationTaxId !== representativeTaxId) {
87
+ throw new Error('Legal-organization verification response contains mismatched organization tax ids between organization and representative credentials.');
88
+ }
89
+ return resolvedTaxId;
90
+ }
91
+ /**
92
+ * Reads `credentialSubject.sameAs` from the legal-representative credential
93
+ * when present.
94
+ */
95
+ export function readLegalRepresentativeSameAsFromResponseBody(responseBody) {
96
+ const pair = readLegalOrganizationVerificationCredentialPairFromResponseBody(responseBody);
97
+ return String(extractCredentialSubject(pair.legalRepresentativeCredential)?.sameAs || '').trim() || undefined;
98
+ }
99
+ /**
100
+ * Reads `credentialSubject.hasCredential.material` continuity data from the
101
+ * legal-representative credential when present.
102
+ */
103
+ export function readLegalRepresentativeBindingFromResponseBody(responseBody) {
104
+ const pair = readLegalOrganizationVerificationCredentialPairFromResponseBody(responseBody);
105
+ return extractRepresentativeCredentialBinding(pair.legalRepresentativeCredential);
106
+ }
@@ -0,0 +1,43 @@
1
+ import type { ClaimsRecord } from '../models/resource-document';
2
+ export type OrganizationAuthorizationUrnInput = Readonly<{
3
+ identifierType: string;
4
+ identifierValue: string;
5
+ }>;
6
+ export type MemberAuthorizationUrnInput = Readonly<{
7
+ organizationUrn?: string;
8
+ identifierType?: string;
9
+ identifierValue?: string;
10
+ memberId: string;
11
+ /** Optional compatibility input. Role must be persisted separately, not inside the canonical member URN. */
12
+ roleCode?: string;
13
+ }>;
14
+ /**
15
+ * Canonical organization authorization identifier used by ledger, consent-like
16
+ * rules, and inter-tenant authorization persistence.
17
+ *
18
+ * Format:
19
+ * - `urn:org:<identifierType-lowercase>:<identifierValue-as-canonical-input>`
20
+ *
21
+ * Examples:
22
+ * - `urn:org:tax:VATES-B12345678`
23
+ * - `urn:org:tax:acme-id`
24
+ */
25
+ export declare function buildOrganizationAuthorizationUrn(input: OrganizationAuthorizationUrnInput): string;
26
+ /**
27
+ * Accepts either the legacy `TYPE|VALUE` input or an already-canonical
28
+ * `urn:org:...` identifier and always returns the canonical URN form.
29
+ */
30
+ export declare function normalizeOrganizationAuthorizationUrn(input: string): string;
31
+ export declare function buildOrganizationAuthorizationUrnFromClaims(claims?: ClaimsRecord): string;
32
+ /**
33
+ * Canonical member authorization identifier rooted in one canonical
34
+ * `urn:org:...`.
35
+ *
36
+ * Format:
37
+ * - `urn:org:<type>:<value>:member:<memberId>`
38
+ *
39
+ * Important rule:
40
+ * - role must be stored as a separate claim, not inside the canonical member
41
+ * identifier
42
+ */
43
+ export declare function buildMemberAuthorizationUrn(input: MemberAuthorizationUrnInput): string;
@@ -0,0 +1,87 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ import { ClaimsOrganizationSchemaorg } from '../constants/schemaorg.js';
3
+ const ORGANIZATION_URN_PREFIX = 'urn:org:';
4
+ function normalizeTypeSegment(identifierType) {
5
+ return String(identifierType || '').trim().toLowerCase();
6
+ }
7
+ function normalizeValueSegment(identifierValue) {
8
+ return String(identifierValue || '').trim();
9
+ }
10
+ /**
11
+ * Canonical organization authorization identifier used by ledger, consent-like
12
+ * rules, and inter-tenant authorization persistence.
13
+ *
14
+ * Format:
15
+ * - `urn:org:<identifierType-lowercase>:<identifierValue-as-canonical-input>`
16
+ *
17
+ * Examples:
18
+ * - `urn:org:tax:VATES-B12345678`
19
+ * - `urn:org:tax:acme-id`
20
+ */
21
+ export function buildOrganizationAuthorizationUrn(input) {
22
+ const identifierType = normalizeTypeSegment(input.identifierType);
23
+ const identifierValue = normalizeValueSegment(input.identifierValue);
24
+ if (!identifierType || !identifierValue) {
25
+ throw new Error('Organization authorization URN requires identifierType and identifierValue.');
26
+ }
27
+ return `${ORGANIZATION_URN_PREFIX}${identifierType}:${identifierValue}`;
28
+ }
29
+ /**
30
+ * Accepts either the legacy `TYPE|VALUE` input or an already-canonical
31
+ * `urn:org:...` identifier and always returns the canonical URN form.
32
+ */
33
+ export function normalizeOrganizationAuthorizationUrn(input) {
34
+ const normalized = String(input || '').trim();
35
+ if (!normalized) {
36
+ throw new Error('Organization authorization identifier cannot be empty.');
37
+ }
38
+ if (normalized.toLowerCase().startsWith(ORGANIZATION_URN_PREFIX)) {
39
+ const parts = normalized.split(':');
40
+ const identifierType = String(parts[2] || '').trim();
41
+ const value = parts.slice(3).join(':').trim();
42
+ return buildOrganizationAuthorizationUrn({
43
+ identifierType,
44
+ identifierValue: value,
45
+ });
46
+ }
47
+ const legacyMatch = normalized.match(/^([^|:]+)\|(.+)$/);
48
+ if (legacyMatch) {
49
+ return buildOrganizationAuthorizationUrn({
50
+ identifierType: legacyMatch[1],
51
+ identifierValue: legacyMatch[2],
52
+ });
53
+ }
54
+ throw new Error(`Unsupported organization authorization identifier format: ${normalized}`);
55
+ }
56
+ export function buildOrganizationAuthorizationUrnFromClaims(claims) {
57
+ const identifierType = String(claims?.[ClaimsOrganizationSchemaorg.identifierType] || '').trim();
58
+ const identifierValue = String(claims?.[ClaimsOrganizationSchemaorg.identifierValue] || '').trim();
59
+ return buildOrganizationAuthorizationUrn({
60
+ identifierType,
61
+ identifierValue,
62
+ });
63
+ }
64
+ /**
65
+ * Canonical member authorization identifier rooted in one canonical
66
+ * `urn:org:...`.
67
+ *
68
+ * Format:
69
+ * - `urn:org:<type>:<value>:member:<memberId>`
70
+ *
71
+ * Important rule:
72
+ * - role must be stored as a separate claim, not inside the canonical member
73
+ * identifier
74
+ */
75
+ export function buildMemberAuthorizationUrn(input) {
76
+ const organizationUrn = input.organizationUrn
77
+ ? normalizeOrganizationAuthorizationUrn(input.organizationUrn)
78
+ : buildOrganizationAuthorizationUrn({
79
+ identifierType: String(input.identifierType || '').trim(),
80
+ identifierValue: String(input.identifierValue || '').trim(),
81
+ });
82
+ const memberId = String(input.memberId || '').trim();
83
+ if (!memberId) {
84
+ throw new Error('Member authorization URN requires memberId.');
85
+ }
86
+ return `${organizationUrn}:member:${memberId}`;
87
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-common-utils-ts",
3
- "version": "2.0.16",
3
+ "version": "2.0.18",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },