@dynamatix/gb-schemas 2.19.1 → 2.20.2

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 (160) hide show
  1. package/README.md +308 -308
  2. package/dist/applicants/applicant-additional-income.model.d.ts +1 -1
  3. package/dist/applicants/applicant-additional-income.type.d.ts +1 -1
  4. package/dist/applicants/applicant-commitment-creditCard.model.d.ts +1 -1
  5. package/dist/applicants/applicant-commitment-loan.model.d.ts +1 -1
  6. package/dist/applicants/applicant-commitment-mortgage.model.d.ts +1 -1
  7. package/dist/applicants/applicant-commitment-residence.model.d.ts +1 -1
  8. package/dist/applicants/applicant-commitment-secureLoan.model.d.ts +1 -1
  9. package/dist/applicants/applicant-commitment-unsecuredLoan.model.d.ts +1 -1
  10. package/dist/applicants/applicant-credit-data.model.d.ts +1 -1
  11. package/dist/applicants/applicant-credit-profile.model.d.ts +1 -1
  12. package/dist/applicants/applicant-credit-report.model.d.ts +19 -19
  13. package/dist/applicants/applicant-credit-report.type.d.ts +1 -1
  14. package/dist/applicants/applicant-direct-debit.model.d.ts +86 -0
  15. package/dist/applicants/applicant-direct-debit.model.d.ts.map +1 -0
  16. package/dist/applicants/applicant-direct-debit.model.js +16 -0
  17. package/dist/applicants/applicant-employment-income.model.d.ts +1 -1
  18. package/dist/applicants/applicant-employment-income.type.d.ts +1 -1
  19. package/dist/applicants/applicant-employment.model.d.ts +1 -1
  20. package/dist/applicants/applicant-expenditure.model.d.ts +1 -1
  21. package/dist/applicants/applicant-expenditure.type.d.ts +1 -1
  22. package/dist/applicants/applicant-income-settings.model.d.ts +1 -1
  23. package/dist/applicants/applicant-income-settings.type.d.ts +1 -1
  24. package/dist/applicants/applicant-income-source.model.d.ts +26 -0
  25. package/dist/applicants/applicant-income-source.model.d.ts.map +1 -0
  26. package/dist/applicants/applicant-income-summary.model.d.ts +1 -1
  27. package/dist/applicants/applicant-income-summary.type.d.ts +1 -1
  28. package/dist/applicants/applicant-income.model.d.ts +160 -0
  29. package/dist/applicants/applicant-income.model.d.ts.map +1 -0
  30. package/dist/applicants/applicant-large-exposure.model.d.ts +1 -1
  31. package/dist/applicants/applicant-large-exposure.type.d.ts +1 -1
  32. package/dist/applicants/applicant-other-income.model.d.ts +85 -0
  33. package/dist/applicants/applicant-other-income.model.d.ts.map +1 -0
  34. package/dist/applicants/applicant-pension-income.model.d.ts +1 -1
  35. package/dist/applicants/applicant-pension-income.type.d.ts +1 -1
  36. package/dist/applicants/applicant-property-income.model.d.ts +1 -1
  37. package/dist/applicants/applicant-property-income.type.d.ts +1 -1
  38. package/dist/applicants/applicant-risk-narrative.model.d.ts +1 -1
  39. package/dist/applicants/applicant-self-employed-income.model.d.ts +1 -1
  40. package/dist/applicants/applicant-self-employed-income.type.d.ts +1 -1
  41. package/dist/applicants/applicant-self-employment.model.d.ts +1 -1
  42. package/dist/applicants/applicant-sole-trader-income.model.d.ts +1 -1
  43. package/dist/applicants/applicant-sole-trader-income.type.d.ts +1 -1
  44. package/dist/applicants/applicant-uk-tax-credits.model.d.ts +1 -1
  45. package/dist/applicants/applicant-uk-tax-credits.type.d.ts +1 -1
  46. package/dist/applicants/applicant-welcome-call.model.d.ts +1 -1
  47. package/dist/applicants/applicant-welcome-call.model.js +9 -9
  48. package/dist/applicants/applicant-welcome-call.type.d.ts +1 -1
  49. package/dist/applicants/applicant.model.d.ts +1 -1
  50. package/dist/applicants/applicant.model.d.ts.map +1 -1
  51. package/dist/applicants/applicant.model.js +2 -0
  52. package/dist/applicants/applicant.type.d.ts +1 -1
  53. package/dist/applications/application-audit.model.d.ts +1 -1
  54. package/dist/applications/application-checklist-Item.model.d.ts +1 -1
  55. package/dist/applications/application-company-model.d.ts +1 -1
  56. package/dist/applications/application-credit-profile.model.d.ts +1 -1
  57. package/dist/applications/application-direct-debit.model.d.ts +4 -4
  58. package/dist/applications/application-direct-debit.model.d.ts.map +1 -1
  59. package/dist/applications/application-direct-debit.model.js +2 -0
  60. package/dist/applications/application-direct-debit.type.d.ts +1 -1
  61. package/dist/applications/application-document.model.d.ts +158 -0
  62. package/dist/applications/application-document.model.d.ts.map +1 -0
  63. package/dist/applications/application-euc.model.d.ts +1 -1
  64. package/dist/applications/application-euc.type.d.ts +1 -1
  65. package/dist/applications/application-fieldconfig.model.d.ts +1 -1
  66. package/dist/applications/application-illustration-model.d.ts +1 -1
  67. package/dist/applications/application-legal.model.d.ts +1 -1
  68. package/dist/applications/application-mortgage.model.d.ts +1 -1
  69. package/dist/applications/application-mortgage.type.d.ts +1 -1
  70. package/dist/applications/application-note.model.d.ts +1 -1
  71. package/dist/applications/application-note.type.d.ts +1 -1
  72. package/dist/applications/application-offer.model.d.ts +1 -1
  73. package/dist/applications/application-offer.type.d.ts +1 -1
  74. package/dist/applications/application-onboarding.model.d.ts +1 -1
  75. package/dist/applications/application-product.model.d.ts +1 -1
  76. package/dist/applications/application-product.type.d.ts +1 -1
  77. package/dist/applications/application-productfeatures.model.d.ts +1 -1
  78. package/dist/applications/application-productfeatures.type.d.ts +1 -1
  79. package/dist/applications/application-rationale.model.d.ts +1 -1
  80. package/dist/applications/application-rationale.type.d.ts +1 -1
  81. package/dist/applications/application-risk-narrative.model.d.ts +1 -1
  82. package/dist/applications/application-valuation-report.model.d.ts +1 -1
  83. package/dist/applications/application-valuation-report.type.d.ts +1 -1
  84. package/dist/applications/application-valuation.model.d.ts +1 -1
  85. package/dist/applications/application-valuation.type.d.ts +1 -1
  86. package/dist/applications/application.model.d.ts +1 -1
  87. package/dist/applications/applications-task.model.d.ts +1 -1
  88. package/dist/applications/applications-task.type.d.ts +1 -1
  89. package/dist/applications/broker.model.d.ts +1 -1
  90. package/dist/applications/broker.type.d.ts +1 -1
  91. package/dist/applications/document.model.d.ts +158 -0
  92. package/dist/applications/document.model.d.ts.map +1 -0
  93. package/dist/applications/euc-country-tier.model.d.ts +65 -0
  94. package/dist/applications/euc-country-tier.model.d.ts.map +1 -0
  95. package/dist/applications/euc-country-tier.model.js +24 -0
  96. package/dist/applications/euc-country-tier.type.d.ts +7 -0
  97. package/dist/applications/euc-country-tier.type.d.ts.map +1 -0
  98. package/dist/applications/euc-country-tier.type.js +1 -0
  99. package/dist/applications/index.d.ts +2 -0
  100. package/dist/applications/index.d.ts.map +1 -1
  101. package/dist/applications/index.js +1 -0
  102. package/dist/applications/productfeatures.model.d.ts +368 -0
  103. package/dist/applications/productfeatures.model.d.ts.map +1 -0
  104. package/dist/applications/solicitor.model.d.ts +1 -1
  105. package/dist/applications/solicitor.type.d.ts +1 -1
  106. package/dist/product-catalogues/product-catalogue.model.d.ts +1 -1
  107. package/dist/product-catalogues/product-definitions.model.d.ts +1 -1
  108. package/dist/product-catalogues/product-definitions.type.d.ts +1 -1
  109. package/dist/product-catalogues/product-variant.model.d.ts +1 -1
  110. package/dist/product-catalogues/product-variant.type.d.ts +1 -1
  111. package/dist/properties/property.model.d.ts +1 -1
  112. package/dist/properties/security.model.d.ts +1 -1
  113. package/dist/shared/alert.model.d.ts +1 -1
  114. package/dist/shared/api-log.model.d.ts +1 -1
  115. package/dist/shared/api-performance.model.d.ts +1 -1
  116. package/dist/shared/api-performance.type.d.ts +1 -1
  117. package/dist/shared/apprivo-sync-journey.model.d.ts +1 -1
  118. package/dist/shared/checklist.model.d.ts +1 -1
  119. package/dist/shared/document-type-model.d.ts +48 -0
  120. package/dist/shared/document-type-model.d.ts.map +1 -0
  121. package/dist/shared/encryption/encrypted-field-map.d.ts +5 -0
  122. package/dist/shared/encryption/encrypted-field-map.d.ts.map +1 -1
  123. package/dist/shared/encryption/encrypted-field-map.js +5 -1
  124. package/dist/shared/encryption/encryption-filter.guard.d.ts +69 -0
  125. package/dist/shared/encryption/encryption-filter.guard.d.ts.map +1 -0
  126. package/dist/shared/encryption/encryption-filter.guard.js +103 -0
  127. package/dist/shared/encryption/encryption.plugin.d.ts +225 -0
  128. package/dist/shared/encryption/encryption.plugin.d.ts.map +1 -0
  129. package/dist/shared/encryption/encryption.plugin.js +372 -0
  130. package/dist/shared/encryption/index.d.ts +2 -0
  131. package/dist/shared/encryption/index.d.ts.map +1 -1
  132. package/dist/shared/encryption/index.js +2 -0
  133. package/dist/shared/index.d.ts +1 -1
  134. package/dist/shared/index.d.ts.map +1 -1
  135. package/dist/shared/index.js +1 -1
  136. package/dist/shared/job-run.model.d.ts +1 -1
  137. package/dist/shared/job-setting.model.d.ts +1 -1
  138. package/dist/shared/lookup-group.model.d.ts +1 -1
  139. package/dist/shared/lookup.model.d.ts +1 -1
  140. package/dist/shared/schema-doc.model.d.ts +1 -1
  141. package/dist/shared/system-parameter.model.d.ts +1 -1
  142. package/dist/shared/task-document.model.d.ts +1 -1
  143. package/dist/shared/task.model.d.ts +1 -1
  144. package/dist/shared/webhook-event.model.d.ts +1 -1
  145. package/dist/shared/workflow-trigger.model.d.ts +1 -1
  146. package/dist/shared/workflow-trigger.type.d.ts +1 -1
  147. package/dist/shared/workflow.middleware.d.ts +1 -1
  148. package/dist/shared/workflow.plugin.d.ts +1 -1
  149. package/dist/types/base.types.d.ts +1 -1
  150. package/dist/underwriter/underwriter.model.d.ts +1 -1
  151. package/dist/users/auth-log.model.d.ts +1 -1
  152. package/dist/users/permission.model.d.ts +1 -1
  153. package/dist/users/role-group.model.d.ts +1 -1
  154. package/dist/users/role.model.d.ts +1 -1
  155. package/dist/users/tasks.model.d.ts +1 -1
  156. package/dist/users/user.model.d.ts +1 -1
  157. package/dist/users/user.type.d.ts +1 -1
  158. package/dist/value-objects/account-number.d.ts +1 -1
  159. package/dist/value-objects/pound.d.ts +1 -1
  160. package/package.json +90 -90
@@ -0,0 +1,372 @@
1
+ import { Schema } from 'mongoose';
2
+ import { EncryptedFieldMapBuilder } from './encrypted-field-map.js';
3
+ import { EncryptionBootstrap } from './encryption.init.js';
4
+ import { EncryptionFilterGuard } from './encryption-filter.guard.js';
5
+ const READ_HOOKS = ['findOne', 'findOneAndUpdate', 'findOneAndReplace', 'findOneAndDelete'];
6
+ const WRITE_QUERY_HOOKS = ['updateOne', 'updateMany', 'findOneAndUpdate', 'findOneAndReplace', 'replaceOne'];
7
+ const GUARDED_HOOKS = [
8
+ 'find', 'findOne', 'countDocuments', 'updateOne', 'updateMany', 'findOneAndUpdate',
9
+ 'findOneAndReplace', 'replaceOne', 'deleteOne', 'deleteMany', 'findOneAndDelete'
10
+ ];
11
+ const UPDATE_CONTAINERS = ['$set', '$setOnInsert'];
12
+ /**
13
+ * Global Mongoose plugin routing `ghEncrypt: true` fields through the
14
+ * {@link EncryptionService} — plumbing only, no crypto in hooks.
15
+ *
16
+ * Write hooks (`save`, `insertMany`, update/replace queries) encrypt
17
+ * annotated values to BSON Binary subtype 6; read hooks (`find`, `findOne`,
18
+ * `findOneAnd*`, `distinct`) decrypt hydrated docs and `.lean()` results.
19
+ * Filters and sorts on encrypted paths fail loud via
20
+ * {@link EncryptionFilterGuard}. When {@link EncryptionBootstrap} is not
21
+ * initialized, every hook is a transparent pass-through so consumers that
22
+ * have not opted in keep working on plaintext.
23
+ *
24
+ * Annotated paths are re-typed to `Mixed` (original type stashed in
25
+ * `ghOriginalType`) so ciphertext survives Mongoose casting. Aggregation is
26
+ * not interceptable and is handled per call site (Enc-5).
27
+ */
28
+ export class EncryptionPlugin {
29
+ constructor() { }
30
+ /**
31
+ * Applies the plugin to a schema: validates and collects annotated
32
+ * paths, re-types them to `Mixed`, and registers guard/write/read hooks.
33
+ * No-op for schemas without annotations; safe to call more than once
34
+ * (encrypt/decrypt transforms are idempotent).
35
+ *
36
+ * @param schema - The Mongoose schema to instrument.
37
+ * @example
38
+ * ```ts
39
+ * const applicantSchema = new mongoose.Schema({
40
+ * firstName: { type: String, ghEncrypt: true }
41
+ * });
42
+ * EncryptionPlugin.apply(applicantSchema);
43
+ * ```
44
+ */
45
+ static apply(schema) {
46
+ const entries = EncryptedFieldMapBuilder.buildForSchema(schema);
47
+ if (entries.length === 0) {
48
+ return;
49
+ }
50
+ for (const entry of entries) {
51
+ EncryptionPlugin.retypeToMixed(schema, entry);
52
+ }
53
+ const paths = entries.map((entry) => entry.path);
54
+ EncryptionPlugin.registerGuardHooks(schema, paths);
55
+ EncryptionPlugin.registerWriteHooks(schema, paths);
56
+ EncryptionPlugin.registerReadHooks(schema, paths);
57
+ }
58
+ /**
59
+ * Re-types one annotated path to `Mixed` so Binary ciphertext is not
60
+ * mangled by the original String/Number cast, stashing the original
61
+ * BSON type in `ghOriginalType` for the field-map/tooling.
62
+ *
63
+ * @param schema - The owning schema.
64
+ * @param entry - The annotated path being re-typed.
65
+ * @example
66
+ * ```ts
67
+ * // internal use only — called by apply()
68
+ * ```
69
+ */
70
+ static retypeToMixed(schema, entry) {
71
+ const schemaType = schema.path(entry.path);
72
+ const options = {
73
+ ...schemaType.options,
74
+ type: Schema.Types.Mixed,
75
+ ghOriginalType: entry.bsonType
76
+ };
77
+ const nested = entry.path
78
+ .split('.')
79
+ .reverse()
80
+ .reduce((acc, segment) => ({ [segment]: acc }), options);
81
+ schema.add(nested);
82
+ }
83
+ /**
84
+ * Registers fail-loud filter/sort guards on every query hook.
85
+ *
86
+ * @param schema - The owning schema.
87
+ * @param paths - Encrypted dot paths of the schema.
88
+ * @example
89
+ * ```ts
90
+ * // internal use only — called by apply()
91
+ * ```
92
+ */
93
+ static registerGuardHooks(schema, paths) {
94
+ schema.pre([...GUARDED_HOOKS], function () {
95
+ if (!EncryptionBootstrap.isInitialized()) {
96
+ return;
97
+ }
98
+ const sort = this.getOptions().sort;
99
+ EncryptionFilterGuard.assertQuerySafe(this.getFilter(), sort, paths);
100
+ });
101
+ }
102
+ /**
103
+ * Registers encrypt-on-write hooks: `save`, `insertMany` and the
104
+ * update/replace query family (`$set`, `$setOnInsert`, dot paths,
105
+ * parent-object values and full replacement docs).
106
+ *
107
+ * @param schema - The owning schema.
108
+ * @param paths - Encrypted dot paths of the schema.
109
+ * @example
110
+ * ```ts
111
+ * // internal use only — called by apply()
112
+ * ```
113
+ */
114
+ static registerWriteHooks(schema, paths) {
115
+ schema.pre('save', async function () {
116
+ await EncryptionPlugin.transformDocument(this, paths, EncryptionPlugin.encryptTransform());
117
+ });
118
+ schema.pre('insertMany', async function (_model, docs) {
119
+ for (const doc of docs ?? []) {
120
+ await EncryptionPlugin.transformTarget(doc, paths, EncryptionPlugin.encryptTransform());
121
+ }
122
+ });
123
+ schema.pre([...WRITE_QUERY_HOOKS], async function () {
124
+ const update = this.getUpdate();
125
+ if (update) {
126
+ await EncryptionPlugin.encryptUpdate(update, paths);
127
+ }
128
+ });
129
+ }
130
+ /**
131
+ * Registers decrypt-on-read hooks: `find`, the `findOne*` family,
132
+ * `distinct`, plus post-`save`/`insertMany` restores so callers keep
133
+ * seeing plaintext on the documents they just persisted.
134
+ *
135
+ * @param schema - The owning schema.
136
+ * @param paths - Encrypted dot paths of the schema.
137
+ * @example
138
+ * ```ts
139
+ * // internal use only — called by apply()
140
+ * ```
141
+ */
142
+ static registerReadHooks(schema, paths) {
143
+ const decrypt = (target) => EncryptionPlugin.transformTarget(target, paths, EncryptionPlugin.decryptTransform());
144
+ schema.post('find', async function (docs) {
145
+ for (const doc of docs ?? []) {
146
+ await decrypt(doc);
147
+ }
148
+ });
149
+ schema.post([...READ_HOOKS], async function (doc) {
150
+ await decrypt(doc);
151
+ });
152
+ schema.post('save', async function () {
153
+ await decrypt(this);
154
+ });
155
+ schema.post('insertMany', async function (docs) {
156
+ for (const doc of docs ?? []) {
157
+ await decrypt(doc);
158
+ }
159
+ });
160
+ schema.post('distinct', async function (values) {
161
+ const service = EncryptionPlugin.activeService();
162
+ if (!service || !Array.isArray(values)) {
163
+ return;
164
+ }
165
+ for (let index = 0; index < values.length; index += 1) {
166
+ if (EncryptionPlugin.isCiphertext(values[index])) {
167
+ values[index] = await service.decrypt(values[index]);
168
+ }
169
+ }
170
+ });
171
+ }
172
+ /**
173
+ * Encrypts annotated values inside an update object: exact dot-path
174
+ * keys, parent-object values containing encrypted leaves, and full
175
+ * replacement documents (updates without atomic operators).
176
+ *
177
+ * @param update - The mutable update object from `Query.getUpdate()`.
178
+ * @param paths - Encrypted dot paths of the schema.
179
+ * @example
180
+ * ```ts
181
+ * // internal use only — called by the update-query pre hook
182
+ * ```
183
+ */
184
+ static async encryptUpdate(update, paths) {
185
+ const transform = EncryptionPlugin.encryptTransform();
186
+ const hasOperators = Object.keys(update).some((key) => key.startsWith('$'));
187
+ if (!hasOperators) {
188
+ await EncryptionPlugin.transformTarget(update, paths, transform);
189
+ return;
190
+ }
191
+ for (const container of UPDATE_CONTAINERS) {
192
+ const target = update[container];
193
+ if (!target) {
194
+ continue;
195
+ }
196
+ for (const [key, value] of Object.entries(target)) {
197
+ for (const path of paths) {
198
+ if (key === path) {
199
+ target[key] = await transform(value);
200
+ }
201
+ else if (path.startsWith(`${key}.`)) {
202
+ await EncryptionPlugin.transformPlain(value, path.slice(key.length + 1).split('.'), transform);
203
+ }
204
+ }
205
+ }
206
+ }
207
+ }
208
+ /**
209
+ * Applies a value transform to every encrypted path of one target,
210
+ * dispatching between hydrated documents (getter-free `get`/`set`) and
211
+ * plain objects (`.lean()` results, insert payloads).
212
+ *
213
+ * @param target - Hydrated document or plain object; non-objects no-op.
214
+ * @param paths - Encrypted dot paths of the schema.
215
+ * @param transform - Value transform (encrypt or decrypt).
216
+ * @example
217
+ * ```ts
218
+ * // internal use only
219
+ * ```
220
+ */
221
+ static async transformTarget(target, paths, transform) {
222
+ if (!target || typeof target !== 'object') {
223
+ return;
224
+ }
225
+ const doc = target;
226
+ const isDocument = typeof doc.get === 'function' && typeof doc.set === 'function';
227
+ for (const path of paths) {
228
+ if (isDocument) {
229
+ await EncryptionPlugin.transformDocPath(doc, path, transform);
230
+ }
231
+ else {
232
+ await EncryptionPlugin.transformPlain(target, path.split('.'), transform);
233
+ }
234
+ }
235
+ }
236
+ /**
237
+ * Applies a transform to every encrypted path of one hydrated document.
238
+ *
239
+ * @param doc - The hydrated Mongoose document.
240
+ * @param paths - Encrypted dot paths of the schema.
241
+ * @param transform - Value transform (encrypt or decrypt).
242
+ * @example
243
+ * ```ts
244
+ * // internal use only
245
+ * ```
246
+ */
247
+ static async transformDocument(doc, paths, transform) {
248
+ for (const path of paths) {
249
+ await EncryptionPlugin.transformDocPath(doc, path, transform);
250
+ }
251
+ }
252
+ /**
253
+ * Transforms one dot path on a hydrated document, reading with getters
254
+ * disabled so value-object formatters never leak into ciphertext.
255
+ *
256
+ * @param doc - The hydrated Mongoose document.
257
+ * @param path - Encrypted dot path.
258
+ * @param transform - Value transform (encrypt or decrypt).
259
+ * @example
260
+ * ```ts
261
+ * // internal use only
262
+ * ```
263
+ */
264
+ static async transformDocPath(doc, path, transform) {
265
+ const value = doc.get(path, null, { getters: false });
266
+ if (value === null || value === undefined) {
267
+ return;
268
+ }
269
+ const next = await transform(value);
270
+ if (next !== value) {
271
+ doc.set(path, next);
272
+ }
273
+ }
274
+ /**
275
+ * Transforms one segmented path on a plain object, descending nested
276
+ * objects and fanning out over arrays.
277
+ *
278
+ * @param target - Plain object (or array element) being walked.
279
+ * @param segments - Remaining path segments.
280
+ * @param transform - Value transform (encrypt or decrypt).
281
+ * @example
282
+ * ```ts
283
+ * // internal use only
284
+ * ```
285
+ */
286
+ static async transformPlain(target, segments, transform) {
287
+ if (target === null || target === undefined || typeof target !== 'object') {
288
+ return;
289
+ }
290
+ if (Array.isArray(target)) {
291
+ for (const element of target) {
292
+ await EncryptionPlugin.transformPlain(element, segments, transform);
293
+ }
294
+ return;
295
+ }
296
+ const [head, ...rest] = segments;
297
+ if (rest.length === 0) {
298
+ const value = target[head];
299
+ if (value !== null && value !== undefined) {
300
+ target[head] = await transform(value);
301
+ }
302
+ return;
303
+ }
304
+ await EncryptionPlugin.transformPlain(target[head], rest, transform);
305
+ }
306
+ /**
307
+ * Builds the encrypt transform: plaintext → Binary; ciphertext and the
308
+ * uninitialized-bootstrap case pass through untouched.
309
+ *
310
+ * @returns Async value transform used by all write hooks.
311
+ * @example
312
+ * ```ts
313
+ * // internal use only
314
+ * ```
315
+ */
316
+ static encryptTransform() {
317
+ return async (value) => {
318
+ const service = EncryptionPlugin.activeService();
319
+ if (!service || EncryptionPlugin.isCiphertext(value)) {
320
+ return value;
321
+ }
322
+ return service.encrypt(value);
323
+ };
324
+ }
325
+ /**
326
+ * Builds the decrypt transform: Binary → plaintext; non-ciphertext and
327
+ * the uninitialized-bootstrap case pass through untouched.
328
+ *
329
+ * @returns Async value transform used by all read hooks.
330
+ * @example
331
+ * ```ts
332
+ * // internal use only
333
+ * ```
334
+ */
335
+ static decryptTransform() {
336
+ return async (value) => {
337
+ const service = EncryptionPlugin.activeService();
338
+ if (!service || !EncryptionPlugin.isCiphertext(value)) {
339
+ return value;
340
+ }
341
+ return service.decrypt(value);
342
+ };
343
+ }
344
+ /**
345
+ * Returns the bootstrapped service, or `null` when encryption is not
346
+ * initialized (pass-through mode for non-opted-in consumers).
347
+ *
348
+ * @returns The active {@link EncryptionService} or `null`.
349
+ * @example
350
+ * ```ts
351
+ * // internal use only
352
+ * ```
353
+ */
354
+ static activeService() {
355
+ return EncryptionBootstrap.isInitialized() ? EncryptionBootstrap.getService() : null;
356
+ }
357
+ /**
358
+ * Duck-type check for BSON Binary subtype 6 (encrypted) values.
359
+ *
360
+ * @param value - Candidate value.
361
+ * @returns `true` when the value is ciphertext.
362
+ * @example
363
+ * ```ts
364
+ * // internal use only
365
+ * ```
366
+ */
367
+ static isCiphertext(value) {
368
+ const candidate = value;
369
+ return Boolean(candidate && typeof candidate === 'object' &&
370
+ candidate._bsontype === 'Binary' && candidate.sub_type === 6);
371
+ }
372
+ }
@@ -2,5 +2,7 @@ export { EncryptionConfig } from './encryption.config.js';
2
2
  export { EncryptionService } from './encryption.service.js';
3
3
  export { EncryptionBootstrap } from './encryption.init.js';
4
4
  export { EncryptedFieldMapBuilder } from './encrypted-field-map.js';
5
+ export { EncryptionPlugin } from './encryption.plugin.js';
6
+ export { EncryptionFilterGuard } from './encryption-filter.guard.js';
5
7
  export type { EncryptedFieldEntry, EncryptedFieldMap } from './encrypted-field-map.js';
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../shared/encryption/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../shared/encryption/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -2,3 +2,5 @@ export { EncryptionConfig } from './encryption.config.js';
2
2
  export { EncryptionService } from './encryption.service.js';
3
3
  export { EncryptionBootstrap } from './encryption.init.js';
4
4
  export { EncryptedFieldMapBuilder } from './encrypted-field-map.js';
5
+ export { EncryptionPlugin } from './encryption.plugin.js';
6
+ export { EncryptionFilterGuard } from './encryption-filter.guard.js';
@@ -16,6 +16,6 @@ export { default as IWebhookEvent } from './webhook-event.type';
16
16
  export { default as ApiPerformanceLogModel } from './api-performance.model';
17
17
  export { default as IApiPerformance } from './api-performance.type';
18
18
  export { initializeWorkflowMiddleware, initializeWorkflowMiddlewareWithCheck, isWorkflowMiddlewareConfigured } from './workflow.init';
19
- export { EncryptionConfig, EncryptionService, EncryptionBootstrap, EncryptedFieldMapBuilder } from './encryption/index.js';
19
+ export { EncryptionConfig, EncryptionService, EncryptionBootstrap, EncryptedFieldMapBuilder, EncryptionPlugin, EncryptionFilterGuard } from './encryption/index.js';
20
20
  export type { EncryptedFieldEntry, EncryptedFieldMap } from './encryption/index.js';
21
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../shared/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAC,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGpE,OAAO,EAAE,4BAA4B,EAAE,qCAAqC,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAC;AAGtI,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAC3H,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../shared/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAC,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGpE,OAAO,EAAE,4BAA4B,EAAE,qCAAqC,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAC;AAGtI,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACpK,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -15,4 +15,4 @@ export { default as ApiPerformanceLogModel } from './api-performance.model';
15
15
  // Workflow middleware initialization exports
16
16
  export { initializeWorkflowMiddleware, initializeWorkflowMiddlewareWithCheck, isWorkflowMiddlewareConfigured } from './workflow.init';
17
17
  // Field-level encryption exports
18
- export { EncryptionConfig, EncryptionService, EncryptionBootstrap, EncryptedFieldMapBuilder } from './encryption/index.js';
18
+ export { EncryptionConfig, EncryptionService, EncryptionBootstrap, EncryptedFieldMapBuilder, EncryptionPlugin, EncryptionFilterGuard } from './encryption/index.js';
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate.js" />
6
6
  /// <reference types="mongoose/types/callback.js" />
7
7
  /// <reference types="mongoose/types/collection.js" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate.js" />
6
6
  /// <reference types="mongoose/types/callback.js" />
7
7
  /// <reference types="mongoose/types/collection.js" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate.js" />
6
6
  /// <reference types="mongoose/types/callback.js" />
7
7
  /// <reference types="mongoose/types/collection.js" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="../shared/encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="../shared/encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="../shared/encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="../shared/encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="../shared/encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="../shared/encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="../shared/encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="../shared/encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />
@@ -1,7 +1,7 @@
1
1
  /// <reference path="../value-objects/pound.d.ts" />
2
2
  /// <reference path="../value-objects/account-number.d.ts" />
3
- /// <reference path="../value-objects/sort-code.d.ts" />
4
3
  /// <reference path="../shared/encryption/encrypted-field-map.d.ts" />
4
+ /// <reference path="../value-objects/sort-code.d.ts" />
5
5
  /// <reference types="mongoose/types/aggregate" />
6
6
  /// <reference types="mongoose/types/callback" />
7
7
  /// <reference types="mongoose/types/collection" />