gdc-common-utils-ts 1.4.15 → 1.4.17

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.
@@ -0,0 +1,20 @@
1
+ export type ActivationRepresentativePolicyErrorCode = 'MISSING_REPRESENTATIVE_DID_WEB' | 'MISSING_REPRESENTATIVE_ROLE_RESPRSN' | 'MISSING_REPRESENTATIVE_CREDENTIAL_MATERIAL' | 'REPRESENTATIVE_TAXID_MISMATCH';
2
+ export type ActivationRepresentativePolicyError = {
3
+ code: ActivationRepresentativePolicyErrorCode;
4
+ message: string;
5
+ };
6
+ export declare function extractCredentialSubject(credential: unknown): Record<string, unknown> | undefined;
7
+ export declare function normalizeTaxIdentifier(value: unknown): string | undefined;
8
+ export declare function extractOrganizationTaxId(organizationCredential: unknown): string | undefined;
9
+ export declare function extractRepresentativeMemberOfTaxId(representativeCredential: unknown): string | undefined;
10
+ export declare function extractRepresentativeRoleCode(representativeCredential: unknown): string | undefined;
11
+ export declare function hasRoleCode(roleCode: string | undefined, requiredCode?: string): boolean;
12
+ export declare function extractRepresentativeCredentialMaterial(representativeCredential: unknown): string | undefined;
13
+ export declare function extractDidWebFromCredential(credential: unknown): string | undefined;
14
+ export declare function buildMemberDidWeb(ownerDidWeb: string, memberId: string, roleCode: string): string;
15
+ export declare function isMemberDidWebUnderOwner(memberDidWeb: string, ownerDidWeb: string): boolean;
16
+ export declare function validateActivationRepresentativePolicy(input: {
17
+ organizationCredential?: unknown;
18
+ representativeCredential?: unknown;
19
+ requiredRoleCode?: string;
20
+ }): ActivationRepresentativePolicyError[];
@@ -0,0 +1,130 @@
1
+ function asObject(value) {
2
+ if (!value || typeof value !== 'object')
3
+ return undefined;
4
+ return value;
5
+ }
6
+ export function extractCredentialSubject(credential) {
7
+ const obj = asObject(credential);
8
+ if (!obj)
9
+ return undefined;
10
+ const subject = obj.credentialSubject;
11
+ if (Array.isArray(subject))
12
+ return asObject(subject[0]);
13
+ return asObject(subject);
14
+ }
15
+ export function normalizeTaxIdentifier(value) {
16
+ const normalized = String(value || '').trim().toUpperCase();
17
+ return normalized || undefined;
18
+ }
19
+ export function extractOrganizationTaxId(organizationCredential) {
20
+ const subject = extractCredentialSubject(organizationCredential) || {};
21
+ const identifier = asObject(subject.identifier);
22
+ return (normalizeTaxIdentifier(subject.taxID)
23
+ || normalizeTaxIdentifier(subject.taxId)
24
+ || normalizeTaxIdentifier(identifier?.value)
25
+ || normalizeTaxIdentifier(subject.identifierValue));
26
+ }
27
+ export function extractRepresentativeMemberOfTaxId(representativeCredential) {
28
+ const subject = extractCredentialSubject(representativeCredential) || {};
29
+ const memberOf = asObject(subject.memberOf) || {};
30
+ const identifier = asObject(memberOf.identifier);
31
+ return (normalizeTaxIdentifier(memberOf.taxID)
32
+ || normalizeTaxIdentifier(memberOf.taxId)
33
+ || normalizeTaxIdentifier(identifier?.value)
34
+ || normalizeTaxIdentifier(memberOf.identifierValue));
35
+ }
36
+ export function extractRepresentativeRoleCode(representativeCredential) {
37
+ const subject = extractCredentialSubject(representativeCredential) || {};
38
+ const occupation = subject.hasOccupation;
39
+ if (typeof occupation === 'string')
40
+ return occupation.trim() || undefined;
41
+ if (occupation && typeof occupation === 'object') {
42
+ const occ = occupation;
43
+ const id = String(occ.identifier || '').trim();
44
+ if (id)
45
+ return id;
46
+ const name = String(occ.name || '').trim();
47
+ if (name)
48
+ return name;
49
+ }
50
+ return undefined;
51
+ }
52
+ export function hasRoleCode(roleCode, requiredCode = 'RESPRSN') {
53
+ const normalizedRole = String(roleCode || '').trim().toUpperCase();
54
+ const normalizedRequired = String(requiredCode || '').trim().toUpperCase();
55
+ return normalizedRole.includes(normalizedRequired);
56
+ }
57
+ export function extractRepresentativeCredentialMaterial(representativeCredential) {
58
+ const subject = extractCredentialSubject(representativeCredential) || {};
59
+ const credentialData = subject.hasCredential;
60
+ if (typeof credentialData === 'string')
61
+ return credentialData.trim() || undefined;
62
+ if (Array.isArray(credentialData)) {
63
+ for (const item of credentialData) {
64
+ const mat = String(item?.material || '').trim();
65
+ if (mat)
66
+ return mat;
67
+ }
68
+ }
69
+ if (credentialData && typeof credentialData === 'object') {
70
+ const mat = String(credentialData?.material || '').trim();
71
+ if (mat)
72
+ return mat;
73
+ }
74
+ return undefined;
75
+ }
76
+ export function extractDidWebFromCredential(credential) {
77
+ const obj = asObject(credential);
78
+ if (!obj)
79
+ return undefined;
80
+ const subject = extractCredentialSubject(obj);
81
+ const didCandidate = String(subject?.id || obj.id || '').trim();
82
+ return didCandidate.startsWith('did:web:') ? didCandidate : undefined;
83
+ }
84
+ export function buildMemberDidWeb(ownerDidWeb, memberId, roleCode) {
85
+ return `${String(ownerDidWeb).trim()}:member:${String(memberId).trim()}:${String(roleCode).trim()}`;
86
+ }
87
+ export function isMemberDidWebUnderOwner(memberDidWeb, ownerDidWeb) {
88
+ const did = String(memberDidWeb || '').trim();
89
+ const owner = String(ownerDidWeb || '').trim();
90
+ if (!did.startsWith('did:web:') || !owner.startsWith('did:web:'))
91
+ return false;
92
+ return did.startsWith(`${owner}:member:`);
93
+ }
94
+ export function validateActivationRepresentativePolicy(input) {
95
+ const errors = [];
96
+ const representativeDid = input.representativeCredential
97
+ ? extractDidWebFromCredential(input.representativeCredential)
98
+ : undefined;
99
+ if (input.representativeCredential && !representativeDid) {
100
+ errors.push({
101
+ code: 'MISSING_REPRESENTATIVE_DID_WEB',
102
+ message: 'ICA-issued representative credential is missing credentialSubject.id did:web.',
103
+ });
104
+ }
105
+ if (!input.representativeCredential)
106
+ return errors;
107
+ const orgTax = extractOrganizationTaxId(input.organizationCredential);
108
+ const repTax = extractRepresentativeMemberOfTaxId(input.representativeCredential);
109
+ if (orgTax && repTax && orgTax !== repTax) {
110
+ errors.push({
111
+ code: 'REPRESENTATIVE_TAXID_MISMATCH',
112
+ message: 'ICA-issued representative credential memberOf.taxID must match organization credential taxID.',
113
+ });
114
+ }
115
+ const roleCode = extractRepresentativeRoleCode(input.representativeCredential);
116
+ if (!hasRoleCode(roleCode, input.requiredRoleCode || 'RESPRSN')) {
117
+ errors.push({
118
+ code: 'MISSING_REPRESENTATIVE_ROLE_RESPRSN',
119
+ message: 'ICA-issued representative credential must include Responsible Party role (RESPRSN) in credentialSubject.hasOccupation.',
120
+ });
121
+ }
122
+ const material = extractRepresentativeCredentialMaterial(input.representativeCredential);
123
+ if (!material) {
124
+ errors.push({
125
+ code: 'MISSING_REPRESENTATIVE_CREDENTIAL_MATERIAL',
126
+ message: 'ICA-issued representative credential is missing credentialSubject.hasCredential.material.',
127
+ });
128
+ }
129
+ return errors;
130
+ }
@@ -1,4 +1,5 @@
1
1
  export * from './actor';
2
+ export * from './activation-policy';
2
3
  export * from './base-convert';
3
4
  export * from './baseN';
4
5
  export * from './bundle';
@@ -1,4 +1,5 @@
1
1
  export * from './actor.js';
2
+ export * from './activation-policy.js';
2
3
  export * from './base-convert.js';
3
4
  export * from './baseN.js';
4
5
  export * from './bundle.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-common-utils-ts",
3
- "version": "1.4.15",
3
+ "version": "1.4.17",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },