@raytio/core 11.4.1 → 11.6.0

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 (137) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +1714 -213
  3. package/dist/accessApplication/api/legacy/convertRelationships.d.ts +3 -5
  4. package/dist/accessApplication/api/legacy/convertRelationships.js +3 -3
  5. package/dist/crypto/cognitoAttributes.d.ts +3 -0
  6. package/dist/crypto/cognitoAttributes.js +15 -4
  7. package/dist/crypto/getAADecryptor.d.ts +1 -1
  8. package/dist/crypto/getAADecryptor.js +1 -3
  9. package/dist/crypto/index.d.ts +3 -0
  10. package/dist/crypto/index.js +6 -0
  11. package/dist/crypto/kdf/argon2.d.ts +67 -0
  12. package/dist/crypto/kdf/argon2.js +99 -0
  13. package/dist/crypto/kdf/index.d.ts +43 -0
  14. package/dist/crypto/kdf/index.js +106 -0
  15. package/dist/crypto/kdf/pbkdf2.d.ts +16 -0
  16. package/dist/crypto/kdf/pbkdf2.js +45 -0
  17. package/dist/crypto/kdf/twoSecretKdf.d.ts +37 -0
  18. package/dist/crypto/kdf/twoSecretKdf.js +66 -0
  19. package/dist/crypto/kdf/types.d.ts +65 -0
  20. package/dist/crypto/kdf/types.js +50 -0
  21. package/dist/crypto/kdf/utils.d.ts +59 -0
  22. package/dist/crypto/kdf/utils.js +110 -0
  23. package/dist/crypto/localSecret/format.d.ts +48 -0
  24. package/dist/crypto/localSecret/format.js +157 -0
  25. package/dist/crypto/localSecret/generator.d.ts +23 -0
  26. package/dist/crypto/localSecret/generator.js +53 -0
  27. package/dist/crypto/localSecret/index.d.ts +12 -0
  28. package/dist/crypto/localSecret/index.js +46 -0
  29. package/dist/crypto/localSecret/storage.d.ts +53 -0
  30. package/dist/crypto/localSecret/storage.js +207 -0
  31. package/dist/crypto/localSecret/types.d.ts +68 -0
  32. package/dist/crypto/localSecret/types.js +31 -0
  33. package/dist/crypto/pgpKey/encryption.d.ts +49 -0
  34. package/dist/crypto/pgpKey/encryption.js +104 -0
  35. package/dist/crypto/pgpKey/export.d.ts +59 -0
  36. package/dist/crypto/pgpKey/export.js +322 -0
  37. package/dist/crypto/pgpKey/format.d.ts +61 -0
  38. package/dist/crypto/pgpKey/format.js +143 -0
  39. package/dist/crypto/pgpKey/generator.d.ts +20 -0
  40. package/dist/crypto/pgpKey/generator.js +76 -0
  41. package/dist/crypto/pgpKey/import.d.ts +69 -0
  42. package/dist/crypto/pgpKey/import.js +239 -0
  43. package/dist/crypto/pgpKey/index.d.ts +19 -0
  44. package/dist/crypto/pgpKey/index.js +67 -0
  45. package/dist/crypto/pgpKey/signing.d.ts +44 -0
  46. package/dist/crypto/pgpKey/signing.js +71 -0
  47. package/dist/crypto/pgpKey/storage.d.ts +43 -0
  48. package/dist/crypto/pgpKey/storage.js +141 -0
  49. package/dist/crypto/pgpKey/types.d.ts +86 -0
  50. package/dist/crypto/pgpKey/types.js +25 -0
  51. package/dist/index.d.ts +1 -0
  52. package/dist/index.js +1 -0
  53. package/dist/rules/calculateScore.d.ts +1 -1
  54. package/dist/rules/convertInstanceToRuleInput.js +99 -97
  55. package/dist/rules/evaluateBadge.d.ts +36 -0
  56. package/dist/rules/evaluateBadge.js +36 -0
  57. package/dist/rules/index.d.ts +1 -0
  58. package/dist/rules/index.js +1 -0
  59. package/dist/rules/types/config.d.ts +1 -1
  60. package/dist/rules/types/dataValueTypes.d.ts +4 -4
  61. package/dist/schema/expandSchema/constants.js +1 -1
  62. package/dist/schema/expandSchema/expandSchema.d.ts +3 -3
  63. package/dist/schema/expandSchema/expandSchema.js +4 -4
  64. package/dist/schema/expandSchema/i18n.d.ts +6 -1
  65. package/dist/schema/expandSchema/i18n.js +32 -4
  66. package/dist/schema/expandSchema/index.d.ts +1 -0
  67. package/dist/schema/expandSchema/index.js +1 -0
  68. package/dist/schema/expandSchema/maybeUseI18n.d.ts +2 -2
  69. package/dist/schema/expandSchema/maybeUseI18n.js +68 -11
  70. package/dist/schema/expandSchema/processSchema.js +14 -5
  71. package/dist/schema/expandSchema/removePrivateFields.d.ts +75 -22
  72. package/dist/schema/expandSchema/sortSchemaProperties.d.ts +4 -1
  73. package/dist/schema/expandSchema/sortSchemaProperties.js +24 -1
  74. package/dist/schema/labels.js +1 -2
  75. package/dist/util/canonicalJsonify.d.ts +7 -1
  76. package/dist/util/canonicalJsonify.js +11 -10
  77. package/dist/verifications/safeHarbour.js +5 -0
  78. package/dist/verifications/verifyCheck/getOwnRealVerifications.js +3 -0
  79. package/dist/verifications/verifyCheck/getSomeoneElsesRealVerifications.js +1 -0
  80. package/package.json +6 -4
  81. package/dist/__tests__/docs.test.d.ts +0 -1
  82. package/dist/__tests__/docs.test.js +0 -24
  83. package/dist/accessApplication/api/__tests__/fetchKeysForSubmission.test.d.ts +0 -1
  84. package/dist/accessApplication/api/__tests__/fetchKeysForSubmission.test.js +0 -28
  85. package/dist/accessApplication/api/__tests__/fetchPOsOrAOsForSubmission.test.d.ts +0 -1
  86. package/dist/accessApplication/api/__tests__/fetchPOsOrAOsForSubmission.test.js +0 -23
  87. package/dist/accessApplication/api/__tests__/fetchRelationshipsForSubmission.test.d.ts +0 -1
  88. package/dist/accessApplication/api/__tests__/fetchRelationshipsForSubmission.test.js +0 -27
  89. package/dist/accessApplication/api/__tests__/getMissingDataForInstance.test.d.ts +0 -1
  90. package/dist/accessApplication/api/__tests__/getMissingDataForInstance.test.js +0 -30
  91. package/dist/accessApplication/api/legacy/__tests__/convertRelationships.test.d.ts +0 -1
  92. package/dist/accessApplication/api/legacy/__tests__/convertRelationships.test.js +0 -37
  93. package/dist/rules/helpers/__tests__/addInfiniteThresholdBoundaries.test.d.ts +0 -1
  94. package/dist/rules/helpers/__tests__/addInfiniteThresholdBoundaries.test.js +0 -27
  95. package/dist/rules/helpers/__tests__/checkTypeofValue.test.d.ts +0 -1
  96. package/dist/rules/helpers/__tests__/checkTypeofValue.test.js +0 -49
  97. package/dist/rules/helpers/__tests__/getValuesFromPath.test.d.ts +0 -1
  98. package/dist/rules/helpers/__tests__/getValuesFromPath.test.js +0 -67
  99. package/dist/rules/helpers/__tests__/thresholds.test.d.ts +0 -1
  100. package/dist/rules/helpers/__tests__/thresholds.test.js +0 -32
  101. package/dist/rules/operators/__tests__/bool.test.d.ts +0 -1
  102. package/dist/rules/operators/__tests__/bool.test.js +0 -21
  103. package/dist/rules/operators/__tests__/date.test.d.ts +0 -1
  104. package/dist/rules/operators/__tests__/date.test.js +0 -81
  105. package/dist/rules/operators/__tests__/hfield.test.d.ts +0 -1
  106. package/dist/rules/operators/__tests__/hfield.test.js +0 -38
  107. package/dist/rules/operators/__tests__/hschema.test.d.ts +0 -1
  108. package/dist/rules/operators/__tests__/hschema.test.js +0 -24
  109. package/dist/rules/operators/__tests__/number.test.d.ts +0 -1
  110. package/dist/rules/operators/__tests__/number.test.js +0 -53
  111. package/dist/rules/operators/__tests__/string.test.d.ts +0 -1
  112. package/dist/rules/operators/__tests__/string.test.js +0 -74
  113. package/dist/schema/expandSchema/__tests__/addLoadingTimes.test.d.ts +0 -1
  114. package/dist/schema/expandSchema/__tests__/addLoadingTimes.test.js +0 -24
  115. package/dist/schema/expandSchema/__tests__/expandSchema.test.d.ts +0 -1
  116. package/dist/schema/expandSchema/__tests__/expandSchema.test.js +0 -96
  117. package/dist/schema/expandSchema/__tests__/i18n.test.d.ts +0 -1
  118. package/dist/schema/expandSchema/__tests__/i18n.test.js +0 -32
  119. package/dist/schema/expandSchema/__tests__/maybeUseI18n.test.d.ts +0 -1
  120. package/dist/schema/expandSchema/__tests__/maybeUseI18n.test.js +0 -98
  121. package/dist/schema/expandSchema/__tests__/processSchema.test.d.ts +0 -1
  122. package/dist/schema/expandSchema/__tests__/processSchema.test.js +0 -326
  123. package/dist/schema/expandSchema/__tests__/sortSchemaProperties.test.d.ts +0 -1
  124. package/dist/schema/expandSchema/__tests__/sortSchemaProperties.test.js +0 -182
  125. package/dist/schema/expandSchema/__tests__/util.test.d.ts +0 -1
  126. package/dist/schema/expandSchema/__tests__/util.test.js +0 -19
  127. package/dist/verifications/cleanInstance.d.ts +0 -9
  128. package/dist/verifications/cleanInstance.js +0 -15
  129. package/dist/verifications/verifyCheck/__tests__/getOwnRealVerifications.test.d.ts +0 -1
  130. package/dist/verifications/verifyCheck/__tests__/getOwnRealVerifications.test.js +0 -217
  131. package/dist/verifications/verifyCheck/__tests__/getSomeoneElsesRealVerifications.test.d.ts +0 -1
  132. package/dist/verifications/verifyCheck/__tests__/getSomeoneElsesRealVerifications.test.js +0 -205
  133. package/dist/verifications/verifyCheck/operations/__tests__/checkOwnVerification.test.d.ts +0 -1
  134. package/dist/verifications/verifyCheck/operations/__tests__/checkOwnVerification.test.js +0 -131
  135. package/dist/verifications/verifyCheck/operations/__tests__/checkSomeoneElsesVerifications.test.d.ts +0 -1
  136. package/dist/verifications/verifyCheck/operations/__tests__/checkSomeoneElsesVerifications.test.js +0 -49
  137. package/dist/verifications/verifyCheck/operations/__tests__/sampleBundle.json +0 -44
@@ -0,0 +1,86 @@
1
+ /**
2
+ * PGP Key Types
3
+ *
4
+ * Types for device-bound PGP keys used for digital signatures.
5
+ * Issue #1374
6
+ */
7
+ /**
8
+ * Supported PGP key algorithms
9
+ */
10
+ export type PGPKeyAlgorithm = "RSA-4096" | "RSA-2048";
11
+ /**
12
+ * PGP private key storage record (IndexedDB)
13
+ */
14
+ export interface StoredPGPPrivateKey {
15
+ /** AES-GCM encrypted private key bytes */
16
+ encryptedPrivateKey: Uint8Array;
17
+ /** 12-byte initialization vector for decryption */
18
+ iv: Uint8Array;
19
+ /** User's Cognito sub (user ID) */
20
+ userId: string;
21
+ /** SHA-256 fingerprint of the public key (first 40 hex chars) */
22
+ keyId: string;
23
+ /** Algorithm identifier for future compatibility */
24
+ algorithm: PGPKeyAlgorithm;
25
+ /** When the key was created */
26
+ createdAt: string;
27
+ /** Unique identifier for the device that generated/imported the key */
28
+ deviceId: string;
29
+ }
30
+ /**
31
+ * PGP public key properties (stored as profile object)
32
+ */
33
+ export interface PGPPublicKeyProperties {
34
+ /** Public key in PEM format (SPKI) */
35
+ publicKey: string;
36
+ /** SHA-256 fingerprint for matching with private key */
37
+ keyId: string;
38
+ /** Algorithm identifier */
39
+ algorithm: PGPKeyAlgorithm;
40
+ /** When the key was created */
41
+ createdAt: string;
42
+ /** Device that generated/imported the key */
43
+ deviceId: string;
44
+ }
45
+ /**
46
+ * Generated key pair (before encryption)
47
+ */
48
+ export interface PGPKeyPair {
49
+ /** Public key in PEM format */
50
+ publicKeyPem: string;
51
+ /** Private key in PKCS8 format (raw bytes) */
52
+ privateKeyBytes: Uint8Array;
53
+ /** Key fingerprint */
54
+ keyId: string;
55
+ /** Algorithm */
56
+ algorithm: PGPKeyAlgorithm;
57
+ }
58
+ /**
59
+ * PGP key storage interface
60
+ */
61
+ export interface PGPKeyStorage {
62
+ /** Store an encrypted private key */
63
+ store(record: StoredPGPPrivateKey): Promise<void>;
64
+ /** Retrieve an encrypted private key */
65
+ get(userId: string): Promise<StoredPGPPrivateKey | null>;
66
+ /** Delete a private key */
67
+ delete(userId: string): Promise<void>;
68
+ /** Check if a private key exists */
69
+ exists(userId: string): Promise<boolean>;
70
+ }
71
+ /**
72
+ * IndexedDB configuration for PGP key storage
73
+ */
74
+ export declare const PGP_KEY_DB_CONFIG: {
75
+ readonly name: "raytio-pgp-keys";
76
+ readonly version: 1;
77
+ readonly storeName: "private-keys";
78
+ };
79
+ /**
80
+ * AES-GCM IV size in bytes
81
+ */
82
+ export declare const AES_GCM_IV_SIZE = 12;
83
+ /**
84
+ * Key fingerprint length (hex characters)
85
+ */
86
+ export declare const KEY_FINGERPRINT_LENGTH = 40;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /**
3
+ * PGP Key Types
4
+ *
5
+ * Types for device-bound PGP keys used for digital signatures.
6
+ * Issue #1374
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.KEY_FINGERPRINT_LENGTH = exports.AES_GCM_IV_SIZE = exports.PGP_KEY_DB_CONFIG = void 0;
10
+ /**
11
+ * IndexedDB configuration for PGP key storage
12
+ */
13
+ exports.PGP_KEY_DB_CONFIG = {
14
+ name: "raytio-pgp-keys",
15
+ version: 1,
16
+ storeName: "private-keys",
17
+ };
18
+ /**
19
+ * AES-GCM IV size in bytes
20
+ */
21
+ exports.AES_GCM_IV_SIZE = 12;
22
+ /**
23
+ * Key fingerprint length (hex characters)
24
+ */
25
+ exports.KEY_FINGERPRINT_LENGTH = 40;
package/dist/index.d.ts CHANGED
@@ -3,4 +3,5 @@ export * from "./crypto";
3
3
  export * from "./general";
4
4
  export * from "./rules";
5
5
  export * from "./schema";
6
+ export * from "./util";
6
7
  export * from "./verifications";
package/dist/index.js CHANGED
@@ -19,4 +19,5 @@ __exportStar(require("./crypto"), exports);
19
19
  __exportStar(require("./general"), exports);
20
20
  __exportStar(require("./rules"), exports);
21
21
  __exportStar(require("./schema"), exports);
22
+ __exportStar(require("./util"), exports);
22
23
  __exportStar(require("./verifications"), exports);
@@ -8,7 +8,7 @@ export declare function evaluateRule(rule: ScoreRule, data: RuleData): {
8
8
  export type ScoreResult = {
9
9
  score: number;
10
10
  category: string;
11
- categoryColour: string | undefined;
11
+ categoryColour: string | null | undefined;
12
12
  diagnostics: {
13
13
  version: string;
14
14
  config: {
@@ -34,107 +34,109 @@ const convertInstanceToRuleInput = async (POs, realVers, getSchema) => {
34
34
  if (schemaName === VERIFICATION_SCHEMA)
35
35
  continue;
36
36
  const schema = await getSchema(schemaName);
37
- const verified = (0, verifications_1.getPOVerification)({ PO, schema, realVers });
38
- // remove anything we can't make rules for (e.g. object), and
39
- // also remove any fields that aren't defined in the schema.
40
- const validFields = Object.entries(PO.properties).filter(([fieldName, value]) => getTypeofFieldValue(value) && schema.properties[fieldName]);
41
- const nonDateProperties = validFields
42
- .filter(d => !isDateField(schema)(d))
43
- .map(([fieldName, value]) => {
44
- var _a;
45
- const verifiedBy = (0, ramda_1.uniq)((_a = realVers
46
- .filter(x => x.belongsToNId === PO.n_id &&
47
- x.fieldName === fieldName &&
48
- x.provider.verifierNId)) === null || _a === void 0 ? void 0 : _a.map(x => x.provider.verifierNId));
49
- const field = {
50
- hField: {
51
- __typeof__: helpers_1.HFieldSymbol,
52
- cameFromSchema: schemaName,
53
- verification: verified.fieldVerifications[fieldName],
54
- verifiedBy,
55
- },
56
- type: getTypeofFieldValue(value),
57
- value,
58
- };
59
- return [fieldName, field];
60
- });
61
- const dateFieldByCategorys = (0, ramda_1.groupBy)(([fieldName]) => schema.properties[fieldName].tags.find(tag => tag.startsWith("group:date_picker")), validFields.filter(isDateField(schema)));
62
- // the three date fields become one pseudo field for the score system
63
- const pseudoDateFields = Object.entries(dateFieldByCategorys).map(([groupTag, _members]) => {
64
- var _a;
65
- // obviously this won't be undefined since we're
66
- // looping through the object.
67
- const members = _members;
68
- const groupName = groupTag.split(":")[2] || "NO_NAME";
69
- const memberFieldNames = members.map(x => x[0]);
70
- const worstVer = (0, ramda_1.sort)((a, b) => b - a, // find the highest enum value (that's the worst)
71
- memberFieldNames.map(f => verified.fieldVerifications[f]))[0];
72
- const fieldVers = (0, ramda_1.uniq)((_a = realVers
73
- .filter(x => x.belongsToNId === PO.n_id &&
74
- memberFieldNames.includes(x.fieldName) &&
75
- x.provider.verifierNId)) === null || _a === void 0 ? void 0 : _a.map(v => v.provider.verifierNId).filter((val) => !!val));
76
- const values = Object.fromEntries(members);
77
- const dayFieldName = memberFieldNames.find(f => { var _a; return (_a = schema.properties[f].tags) === null || _a === void 0 ? void 0 : _a.includes("date_component:day"); });
78
- const monthFieldName = memberFieldNames.find(f => { var _a; return (_a = schema.properties[f].tags) === null || _a === void 0 ? void 0 : _a.includes("date_component:month"); });
79
- const yearFieldName = memberFieldNames.find(f => { var _a; return (_a = schema.properties[f].tags) === null || _a === void 0 ? void 0 : _a.includes("date_component:year"); });
80
- if (!dayFieldName || !monthFieldName || !yearFieldName) {
81
- throw new Error("Failed to infer date component field");
82
- }
83
- const isoString = [
84
- values[yearFieldName],
85
- `${values[monthFieldName]}`.padStart(2, "0"),
86
- `${values[dayFieldName]}`.padStart(2, "0"),
87
- ].join("-");
88
- const pseudoField = {
89
- hField: {
90
- __typeof__: helpers_1.HFieldSymbol,
91
- cameFromSchema: schemaName,
92
- verification: worstVer,
93
- verifiedBy: fieldVers,
94
- },
95
- type: "Date",
96
- value: new Date(isoString),
97
- };
98
- return [`__group_${groupName}`, pseudoField];
99
- });
100
- const deepProperties = Object.entries(PO.properties)
101
- .filter(([fieldName, fieldValue]) => {
102
- const field = schema.properties[fieldName];
103
- return (field &&
104
- field.type === "object" &&
105
- field.properties &&
106
- fieldValue &&
107
- typeof fieldValue === "object");
108
- })
109
- .flatMap(([fieldName, fieldValue]) => {
110
- const subFields = Object.keys(schema.properties[fieldName].properties);
111
- return subFields.map(subFieldName => {
112
- const value = fieldValue[subFieldName];
113
- const hsubfield = {
114
- hField: null, // you can't access metadata on a subfield
37
+ if (schema) {
38
+ const verified = (0, verifications_1.getPOVerification)({ PO, schema, realVers });
39
+ // remove anything we can't make rules for (e.g. object), and
40
+ // also remove any fields that aren't defined in the schema.
41
+ const validFields = Object.entries(PO.properties).filter(([fieldName, value]) => getTypeofFieldValue(value) && schema.properties[fieldName]);
42
+ const nonDateProperties = validFields
43
+ .filter(d => !isDateField(schema)(d))
44
+ .map(([fieldName, value]) => {
45
+ var _a;
46
+ const verifiedBy = (0, ramda_1.uniq)((_a = realVers
47
+ .filter(x => x.belongsToNId === PO.n_id &&
48
+ x.fieldName === fieldName &&
49
+ x.provider.verifierNId)) === null || _a === void 0 ? void 0 : _a.map(x => x.provider.verifierNId));
50
+ const field = {
51
+ hField: {
52
+ __typeof__: helpers_1.HFieldSymbol,
53
+ cameFromSchema: schemaName,
54
+ verification: verified.fieldVerifications[fieldName],
55
+ verifiedBy,
56
+ },
115
57
  type: getTypeofFieldValue(value),
116
58
  value,
117
59
  };
118
- return [`${fieldName}|${subFieldName}`, hsubfield];
60
+ return [fieldName, field];
61
+ });
62
+ const dateFieldByCategorys = (0, ramda_1.groupBy)(([fieldName]) => schema.properties[fieldName].tags.find(tag => tag.startsWith("group:date_picker")), validFields.filter(isDateField(schema)));
63
+ // the three date fields become one pseudo field for the score system
64
+ const pseudoDateFields = Object.entries(dateFieldByCategorys).map(([groupTag, _members]) => {
65
+ var _a;
66
+ // obviously this won't be undefined since we're
67
+ // looping through the object.
68
+ const members = _members;
69
+ const groupName = groupTag.split(":")[2] || "NO_NAME";
70
+ const memberFieldNames = members.map(x => x[0]);
71
+ const worstVer = (0, ramda_1.sort)((a, b) => b - a, // find the highest enum value (that's the worst)
72
+ memberFieldNames.map(f => verified.fieldVerifications[f]))[0];
73
+ const fieldVers = (0, ramda_1.uniq)((_a = realVers
74
+ .filter(x => x.belongsToNId === PO.n_id &&
75
+ memberFieldNames.includes(x.fieldName) &&
76
+ x.provider.verifierNId)) === null || _a === void 0 ? void 0 : _a.map(v => v.provider.verifierNId).filter((val) => !!val));
77
+ const values = Object.fromEntries(members);
78
+ const dayFieldName = memberFieldNames.find(f => { var _a; return (_a = schema.properties[f].tags) === null || _a === void 0 ? void 0 : _a.includes("date_component:day"); });
79
+ const monthFieldName = memberFieldNames.find(f => { var _a; return (_a = schema.properties[f].tags) === null || _a === void 0 ? void 0 : _a.includes("date_component:month"); });
80
+ const yearFieldName = memberFieldNames.find(f => { var _a; return (_a = schema.properties[f].tags) === null || _a === void 0 ? void 0 : _a.includes("date_component:year"); });
81
+ if (!dayFieldName || !monthFieldName || !yearFieldName) {
82
+ throw new Error("Failed to infer date component field");
83
+ }
84
+ const isoString = [
85
+ values[yearFieldName],
86
+ `${values[monthFieldName]}`.padStart(2, "0"),
87
+ `${values[dayFieldName]}`.padStart(2, "0"),
88
+ ].join("-");
89
+ const pseudoField = {
90
+ hField: {
91
+ __typeof__: helpers_1.HFieldSymbol,
92
+ cameFromSchema: schemaName,
93
+ verification: worstVer,
94
+ verifiedBy: fieldVers,
95
+ },
96
+ type: "Date",
97
+ value: new Date(isoString),
98
+ };
99
+ return [`__group_${groupName}`, pseudoField];
100
+ });
101
+ const deepProperties = Object.entries(PO.properties)
102
+ .filter(([fieldName, fieldValue]) => {
103
+ const field = schema.properties[fieldName];
104
+ return (field &&
105
+ field.type === "object" &&
106
+ field.properties &&
107
+ fieldValue &&
108
+ typeof fieldValue === "object");
109
+ })
110
+ .flatMap(([fieldName, fieldValue]) => {
111
+ const subFields = Object.keys(schema.properties[fieldName].properties);
112
+ return subFields.map(subFieldName => {
113
+ const value = fieldValue[subFieldName];
114
+ const hsubfield = {
115
+ hField: null, // you can't access metadata on a subfield
116
+ type: getTypeofFieldValue(value),
117
+ value,
118
+ };
119
+ return [`${fieldName}|${subFieldName}`, hsubfield];
120
+ });
121
+ });
122
+ // eslint-disable-next-line fp/no-mutation
123
+ out[schemaName] || (out[schemaName] = []);
124
+ // eslint-disable-next-line fp/no-mutating-methods
125
+ out[schemaName].push({
126
+ hSchema: {
127
+ __typeof__: helpers_1.HSchemaSymbol,
128
+ verification: verified.status,
129
+ verifiedBy: verified.details.verifiers
130
+ .map(x => x.verifierNId)
131
+ .filter((val) => !!val),
132
+ },
133
+ properties: Object.fromEntries([
134
+ ...nonDateProperties,
135
+ ...pseudoDateFields,
136
+ ...deepProperties,
137
+ ]),
119
138
  });
120
- });
121
- // eslint-disable-next-line fp/no-mutation
122
- out[schemaName] || (out[schemaName] = []);
123
- // eslint-disable-next-line fp/no-mutating-methods
124
- out[schemaName].push({
125
- hSchema: {
126
- __typeof__: helpers_1.HSchemaSymbol,
127
- verification: verified.status,
128
- verifiedBy: verified.details.verifiers
129
- .map(x => x.verifierNId)
130
- .filter((val) => !!val),
131
- },
132
- properties: Object.fromEntries([
133
- ...nonDateProperties,
134
- ...pseudoDateFields,
135
- ...deepProperties,
136
- ]),
137
- });
139
+ }
138
140
  }
139
141
  return out;
140
142
  };
@@ -0,0 +1,36 @@
1
+ import type { BId, CommonFields } from "@raytio/types";
2
+ import type { RuleData, ScoreConfig } from "./types";
3
+ import type { ScoreResult } from "./calculateScore";
4
+ /** Standard badge states - consistent across all badges */
5
+ export type BadgeState = "not_met" | "partially_met" | "fully_met";
6
+ /** Display configuration for a single badge state */
7
+ export type BadgeStateDisplay = {
8
+ label: string;
9
+ color: string;
10
+ icon: string;
11
+ };
12
+ /** Badge definition as stored in dsm_schema_badges */
13
+ export type BadgeDefinition = CommonFields<BId> & {
14
+ name: string;
15
+ display: {
16
+ states: Record<BadgeState, BadgeStateDisplay>;
17
+ };
18
+ ruleset: ScoreConfig;
19
+ };
20
+ /** Result of evaluating a badge for a user */
21
+ export type BadgeResult = {
22
+ badgeId: string;
23
+ badgeName: string;
24
+ state: BadgeState;
25
+ display: BadgeStateDisplay;
26
+ diagnostics: ScoreResult["diagnostics"];
27
+ };
28
+ /**
29
+ * Evaluate a single badge definition against user data.
30
+ * Thin wrapper around calculateScore() -- threshold names map to badge states.
31
+ */
32
+ export declare function evaluateBadge(badge: BadgeDefinition, ruleData: RuleData): Promise<BadgeResult>;
33
+ /**
34
+ * Evaluate all active badge definitions against user data.
35
+ */
36
+ export declare function evaluateUserBadges(badges: BadgeDefinition[], ruleData: RuleData): Promise<BadgeResult[]>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.evaluateBadge = evaluateBadge;
4
+ exports.evaluateUserBadges = evaluateUserBadges;
5
+ const calculateScore_1 = require("./calculateScore");
6
+ const VALID_BADGE_STATES = [
7
+ "not_met",
8
+ "partially_met",
9
+ "fully_met",
10
+ ];
11
+ /**
12
+ * Evaluate a single badge definition against user data.
13
+ * Thin wrapper around calculateScore() -- threshold names map to badge states.
14
+ */
15
+ async function evaluateBadge(badge, ruleData) {
16
+ const scoreResult = await (0, calculateScore_1.calculateScore)(badge.ruleset, ruleData);
17
+ const state = scoreResult.category;
18
+ if (!VALID_BADGE_STATES.includes(state)) {
19
+ throw new Error(`Score category "${scoreResult.category}" is not a valid BadgeState. ` +
20
+ `Expected one of: ${VALID_BADGE_STATES.join(", ")}`);
21
+ }
22
+ return {
23
+ badgeId: badge.id,
24
+ badgeName: badge.name,
25
+ state,
26
+ display: badge.display.states[state],
27
+ diagnostics: scoreResult.diagnostics,
28
+ };
29
+ }
30
+ /**
31
+ * Evaluate all active badge definitions against user data.
32
+ */
33
+ async function evaluateUserBadges(badges, ruleData) {
34
+ const active = badges.filter(b => b.active);
35
+ return Promise.all(active.map(b => evaluateBadge(b, ruleData)));
36
+ }
@@ -1,5 +1,6 @@
1
1
  export * from "./calculateScore";
2
2
  export * from "./convertInstanceToRuleInput";
3
+ export * from "./evaluateBadge";
3
4
  export * from "./validate";
4
5
  export * from "./types/config";
5
6
  export * from "./helpers/thresholds";
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.scoreOperators = void 0;
18
18
  __exportStar(require("./calculateScore"), exports);
19
19
  __exportStar(require("./convertInstanceToRuleInput"), exports);
20
+ __exportStar(require("./evaluateBadge"), exports);
20
21
  __exportStar(require("./validate"), exports);
21
22
  __exportStar(require("./types/config"), exports);
22
23
  __exportStar(require("./helpers/thresholds"), exports);
@@ -81,7 +81,7 @@ export type ScoreThreshold = {
81
81
  * A hex code, including the hash.
82
82
  * For compatibility reasons we must assume it could be missing
83
83
  */
84
- colour: string | undefined;
84
+ colour: string | null | undefined;
85
85
  };
86
86
  /** @ignore */
87
87
  export type Combinator = "+" | "*";
@@ -1,18 +1,18 @@
1
- import type { FieldVerification, NId, POVerification, SchemaName } from "@raytio/types";
1
+ import type { FieldVerification, MId, POVerification, SchemaName } from "@raytio/types";
2
2
  import type { HFieldSymbol, HSchemaSymbol } from "../helpers";
3
3
  /** undefined if not shared */
4
4
  export type HField = {
5
5
  __typeof__: typeof HFieldSymbol;
6
6
  verification: FieldVerification;
7
- verifiedBy: readonly NId[];
7
+ verifiedBy: readonly MId[];
8
8
  cameFromSchema: SchemaName;
9
9
  };
10
10
  /** undefined if not shared */
11
11
  export type HSchema = {
12
12
  __typeof__: typeof HSchemaSymbol;
13
13
  verification?: POVerification;
14
- verifiedBy: readonly NId[];
14
+ verifiedBy: readonly MId[];
15
15
  };
16
16
  export declare const DATE_UNITS: readonly ["ms", "s", "m", "h", "D", "M", "W", "Y"];
17
17
  export type DateUnit = (typeof DATE_UNITS)[number];
18
- export type GetTSType<T> = T extends "Bool" ? boolean : T extends "Number" ? number : T extends "String" ? string : T extends "Date" ? Date : T extends "Array" ? unknown[] : T extends "HField" ? HField : T extends "HSchema" ? HSchema : T extends "DateUnit" ? DateUnit : T extends "RegEx" ? RegExp : T extends "Verifier" ? NId : T extends "FieldVerification" ? FieldVerification : T extends "POVerification" ? POVerification : never;
18
+ export type GetTSType<T> = T extends "Bool" ? boolean : T extends "Number" ? number : T extends "String" ? string : T extends "Date" ? Date : T extends "Array" ? unknown[] : T extends "HField" ? HField : T extends "HSchema" ? HSchema : T extends "DateUnit" ? DateUnit : T extends "RegEx" ? RegExp : T extends "Verifier" ? MId : T extends "FieldVerification" ? FieldVerification : T extends "POVerification" ? POVerification : never;
@@ -7,5 +7,5 @@ exports.TAG_DENYLIST = [
7
7
  "type:globally_unique_field",
8
8
  "type:marketplace",
9
9
  "type:service_offer",
10
- "type:service_provider",
10
+ "type:merchant",
11
11
  ];
@@ -1,7 +1,7 @@
1
- import type { Schema, WrappedSchema } from "@raytio/types";
1
+ import type { FndI18nEntry, Schema, WrappedSchema } from "@raytio/types";
2
2
  /**
3
- * ❣️ This is the main function to transform a schema from
3
+ * This is the main function to transform a schema from
4
4
  * the JSON that the API returns, into a `Schema` object that's useful
5
5
  * to the client.
6
6
  */
7
- export declare function expandSchema(wrappedSchema: WrappedSchema, allUnexpandedSchemas: WrappedSchema[], userLocales: readonly string[]): Schema;
7
+ export declare function expandSchema(wrappedSchema: WrappedSchema, allUnexpandedSchemas: WrappedSchema[], userLocales: readonly string[], fndI18nEntries?: FndI18nEntry[]): Schema;
@@ -7,12 +7,12 @@ const processSchema_1 = require("./processSchema");
7
7
  const removePrivateFields_1 = require("./removePrivateFields");
8
8
  const unwrapSchema_1 = require("./unwrapSchema");
9
9
  /**
10
- * ❣️ This is the main function to transform a schema from
10
+ * This is the main function to transform a schema from
11
11
  * the JSON that the API returns, into a `Schema` object that's useful
12
12
  * to the client.
13
13
  */
14
- function expandSchema(wrappedSchema, allUnexpandedSchemas, userLocales) {
15
- // TODO: use Ramda's pipe
16
- const schema = (0, removePrivateFields_1.removePrivateFields)((0, maybeUseI18n_1.maybeUseI18n)((0, addLoadingTimes_1.addLoadingTimes)((0, processSchema_1.processSchema)((0, unwrapSchema_1.unwrapSchema)(wrappedSchema), allUnexpandedSchemas)), userLocales));
14
+ // eslint-disable-next-line max-params
15
+ function expandSchema(wrappedSchema, allUnexpandedSchemas, userLocales, fndI18nEntries) {
16
+ const schema = (0, removePrivateFields_1.removePrivateFields)((0, maybeUseI18n_1.maybeUseI18n)((0, addLoadingTimes_1.addLoadingTimes)((0, processSchema_1.processSchema)((0, unwrapSchema_1.unwrapSchema)(wrappedSchema), allUnexpandedSchemas)), userLocales, fndI18nEntries));
17
17
  return Object.assign({ wasExpandedByClient: true }, schema);
18
18
  }
@@ -1,5 +1,10 @@
1
1
  /**
2
2
  * Selects the most suitable locale to use from a list of options.
3
- * Returns undefined if there is no language that the user speaks
3
+ * Returns undefined if there is no language that the user speaks.
4
+ *
5
+ * Priority order:
6
+ * 1. Exact full locale match (e.g., user has en-NZ, schema has en-NZ)
7
+ * 2. Base language match (e.g., user has en-US, schema has en)
8
+ * 3. Any locale with matching base language (e.g., user has de-DE, schema has de-AT)
4
9
  */
5
10
  export declare const findSuitableLocale: (options: string[], langs: readonly string[]) => string | undefined;
@@ -10,11 +10,39 @@ const getAllLocales = (langs) => (0, ramda_1.uniq)(langs.flatMap(locale => [
10
10
  exports.getAllLocales = getAllLocales;
11
11
  /**
12
12
  * Selects the most suitable locale to use from a list of options.
13
- * Returns undefined if there is no language that the user speaks
13
+ * Returns undefined if there is no language that the user speaks.
14
+ *
15
+ * Priority order:
16
+ * 1. Exact full locale match (e.g., user has en-NZ, schema has en-NZ)
17
+ * 2. Base language match (e.g., user has en-US, schema has en)
18
+ * 3. Any locale with matching base language (e.g., user has de-DE, schema has de-AT)
14
19
  */
15
20
  const findSuitableLocale = (options, langs) => {
16
- const userLocales = (0, exports.getAllLocales)(langs);
17
- return (userLocales.find(locale => options.includes(locale)) ||
18
- options.find(locale => userLocales.includes(locale.split("-")[0])));
21
+ // Get user's full locales (e.g., "en-NZ") in lowercase
22
+ const userFullLocales = langs.map(l => l.toLowerCase());
23
+ // Get user's base languages (e.g., "en") in lowercase
24
+ const userBaseLanguages = (0, ramda_1.uniq)(langs.map(l => l.toLowerCase().split("-")[0]));
25
+ // First, try to find an exact full locale match (case-insensitive)
26
+ // e.g., user has en-NZ, schema has en-NZ → returns "en-NZ"
27
+ for (const userLocale of userFullLocales) {
28
+ const match = options.find(opt => opt.toLowerCase() === userLocale);
29
+ if (match)
30
+ return match;
31
+ }
32
+ // Then, fall back to base language match
33
+ // e.g., user has en-US, schema has en → returns "en"
34
+ for (const baseLang of userBaseLanguages) {
35
+ const match = options.find(opt => opt.toLowerCase() === baseLang);
36
+ if (match)
37
+ return match;
38
+ }
39
+ // Finally, check if any option's base language matches user's base language
40
+ // e.g., user has de-DE, schema has de-AT → returns "de-AT"
41
+ for (const baseLang of userBaseLanguages) {
42
+ const match = options.find(opt => opt.toLowerCase().split("-")[0] === baseLang);
43
+ if (match)
44
+ return match;
45
+ }
46
+ return undefined;
19
47
  };
20
48
  exports.findSuitableLocale = findSuitableLocale;
@@ -1,3 +1,4 @@
1
1
  export * from "./expandSchema";
2
2
  export * from "./sortSchemaProperties";
3
+ export * from "./constants";
3
4
  export { findSuitableLocale } from "./i18n";
@@ -17,5 +17,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.findSuitableLocale = void 0;
18
18
  __exportStar(require("./expandSchema"), exports);
19
19
  __exportStar(require("./sortSchemaProperties"), exports);
20
+ __exportStar(require("./constants"), exports);
20
21
  var i18n_1 = require("./i18n");
21
22
  Object.defineProperty(exports, "findSuitableLocale", { enumerable: true, get: function () { return i18n_1.findSuitableLocale; } });
@@ -1,2 +1,2 @@
1
- import type { Schema } from "@raytio/types";
2
- export declare const maybeUseI18n: (schema: Schema, userLocales: readonly string[]) => Schema;
1
+ import type { FndI18nEntry, Schema } from "@raytio/types";
2
+ export declare const maybeUseI18n: (schema: Schema, userLocales: readonly string[], fndI18nEntries?: FndI18nEntry[]) => Schema;