@proteinjs/db 1.35.1 → 1.37.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 (165) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/generated/index.d.ts.map +1 -1
  3. package/dist/generated/index.js +7 -1
  4. package/dist/generated/index.js.map +1 -1
  5. package/dist/generated/test/index.d.ts.map +1 -1
  6. package/dist/generated/test/index.js +7 -1
  7. package/dist/generated/test/index.js.map +1 -1
  8. package/dist/index.d.ts +15 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +15 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/src/Columns.d.ts +5 -1
  13. package/dist/src/Columns.d.ts.map +1 -1
  14. package/dist/src/Columns.js +2 -1
  15. package/dist/src/Columns.js.map +1 -1
  16. package/dist/src/Db.d.ts +25 -0
  17. package/dist/src/Db.d.ts.map +1 -1
  18. package/dist/src/Db.js +219 -22
  19. package/dist/src/Db.js.map +1 -1
  20. package/dist/src/Record.d.ts +7 -1
  21. package/dist/src/Record.d.ts.map +1 -1
  22. package/dist/src/Record.js +56 -21
  23. package/dist/src/Record.js.map +1 -1
  24. package/dist/src/Table.d.ts +82 -1
  25. package/dist/src/Table.d.ts.map +1 -1
  26. package/dist/src/Table.js +24 -1
  27. package/dist/src/Table.js.map +1 -1
  28. package/dist/src/TableQueryTransformProvider.d.ts +17 -0
  29. package/dist/src/TableQueryTransformProvider.d.ts.map +1 -0
  30. package/dist/src/TableQueryTransformProvider.js +34 -0
  31. package/dist/src/TableQueryTransformProvider.js.map +1 -0
  32. package/dist/src/encryption/Base64Url.d.ts +12 -0
  33. package/dist/src/encryption/Base64Url.d.ts.map +1 -0
  34. package/dist/src/encryption/Base64Url.js +21 -0
  35. package/dist/src/encryption/Base64Url.js.map +1 -0
  36. package/dist/src/encryption/DataEncryptionKeyTable.d.ts +33 -0
  37. package/dist/src/encryption/DataEncryptionKeyTable.d.ts.map +1 -0
  38. package/dist/src/encryption/DataEncryptionKeyTable.js +45 -0
  39. package/dist/src/encryption/DataEncryptionKeyTable.js.map +1 -0
  40. package/dist/src/encryption/DataKeyStore.d.ts +84 -0
  41. package/dist/src/encryption/DataKeyStore.d.ts.map +1 -0
  42. package/dist/src/encryption/DataKeyStore.js +481 -0
  43. package/dist/src/encryption/DataKeyStore.js.map +1 -0
  44. package/dist/src/encryption/DbEncryptionConfig.d.ts +62 -0
  45. package/dist/src/encryption/DbEncryptionConfig.d.ts.map +1 -0
  46. package/dist/src/encryption/DbEncryptionConfig.js +67 -0
  47. package/dist/src/encryption/DbEncryptionConfig.js.map +1 -0
  48. package/dist/src/encryption/EncryptedColumnQueryError.d.ts +10 -0
  49. package/dist/src/encryption/EncryptedColumnQueryError.d.ts.map +1 -0
  50. package/dist/src/encryption/EncryptedColumnQueryError.js +38 -0
  51. package/dist/src/encryption/EncryptedColumnQueryError.js.map +1 -0
  52. package/dist/src/encryption/EncryptedColumnQueryTransform.d.ts +52 -0
  53. package/dist/src/encryption/EncryptedColumnQueryTransform.d.ts.map +1 -0
  54. package/dist/src/encryption/EncryptedColumnQueryTransform.js +423 -0
  55. package/dist/src/encryption/EncryptedColumnQueryTransform.js.map +1 -0
  56. package/dist/src/encryption/EncryptedColumns.d.ts +69 -0
  57. package/dist/src/encryption/EncryptedColumns.d.ts.map +1 -0
  58. package/dist/src/encryption/EncryptedColumns.js +286 -0
  59. package/dist/src/encryption/EncryptedColumns.js.map +1 -0
  60. package/dist/src/encryption/EncryptionDerivedTableRegistry.d.ts +20 -0
  61. package/dist/src/encryption/EncryptionDerivedTableRegistry.d.ts.map +1 -0
  62. package/dist/src/encryption/EncryptionDerivedTableRegistry.js +36 -0
  63. package/dist/src/encryption/EncryptionDerivedTableRegistry.js.map +1 -0
  64. package/dist/src/encryption/EncryptionEnvelope.d.ts +25 -0
  65. package/dist/src/encryption/EncryptionEnvelope.d.ts.map +1 -0
  66. package/dist/src/encryption/EncryptionEnvelope.js +59 -0
  67. package/dist/src/encryption/EncryptionEnvelope.js.map +1 -0
  68. package/dist/src/encryption/EncryptionLifecycleWalker.d.ts +65 -0
  69. package/dist/src/encryption/EncryptionLifecycleWalker.d.ts.map +1 -0
  70. package/dist/src/encryption/EncryptionLifecycleWalker.js +343 -0
  71. package/dist/src/encryption/EncryptionLifecycleWalker.js.map +1 -0
  72. package/dist/src/encryption/EncryptionRecordHooks.d.ts +47 -0
  73. package/dist/src/encryption/EncryptionRecordHooks.d.ts.map +1 -0
  74. package/dist/src/encryption/EncryptionRecordHooks.js +229 -0
  75. package/dist/src/encryption/EncryptionRecordHooks.js.map +1 -0
  76. package/dist/src/encryption/EncryptionTokenMaintenance.d.ts +34 -0
  77. package/dist/src/encryption/EncryptionTokenMaintenance.d.ts.map +1 -0
  78. package/dist/src/encryption/EncryptionTokenMaintenance.js +211 -0
  79. package/dist/src/encryption/EncryptionTokenMaintenance.js.map +1 -0
  80. package/dist/src/encryption/InMemoryMasterKeyProvider.d.ts +20 -0
  81. package/dist/src/encryption/InMemoryMasterKeyProvider.d.ts.map +1 -0
  82. package/dist/src/encryption/InMemoryMasterKeyProvider.js +87 -0
  83. package/dist/src/encryption/InMemoryMasterKeyProvider.js.map +1 -0
  84. package/dist/src/encryption/MasterKeyProvider.d.ts +27 -0
  85. package/dist/src/encryption/MasterKeyProvider.d.ts.map +1 -0
  86. package/dist/src/encryption/MasterKeyProvider.js +3 -0
  87. package/dist/src/encryption/MasterKeyProvider.js.map +1 -0
  88. package/dist/src/encryption/SearchTokenizer.d.ts +49 -0
  89. package/dist/src/encryption/SearchTokenizer.d.ts.map +1 -0
  90. package/dist/src/encryption/SearchTokenizer.js +106 -0
  91. package/dist/src/encryption/SearchTokenizer.js.map +1 -0
  92. package/dist/src/schema/TableManager.d.ts +10 -0
  93. package/dist/src/schema/TableManager.d.ts.map +1 -1
  94. package/dist/src/schema/TableManager.js +62 -5
  95. package/dist/src/schema/TableManager.js.map +1 -1
  96. package/dist/src/tables/MigrationTable.d.ts +2 -2
  97. package/dist/test/EncryptedColumnsSchema.test.d.ts +2 -0
  98. package/dist/test/EncryptedColumnsSchema.test.d.ts.map +1 -0
  99. package/dist/test/EncryptedColumnsSchema.test.js +151 -0
  100. package/dist/test/EncryptedColumnsSchema.test.js.map +1 -0
  101. package/dist/test/EncryptionEnvelope.test.d.ts +2 -0
  102. package/dist/test/EncryptionEnvelope.test.d.ts.map +1 -0
  103. package/dist/test/EncryptionEnvelope.test.js +109 -0
  104. package/dist/test/EncryptionEnvelope.test.js.map +1 -0
  105. package/dist/test/EncryptionQueryContract.test.d.ts +2 -0
  106. package/dist/test/EncryptionQueryContract.test.d.ts.map +1 -0
  107. package/dist/test/EncryptionQueryContract.test.js +399 -0
  108. package/dist/test/EncryptionQueryContract.test.js.map +1 -0
  109. package/dist/test/SearchTokenizer.test.d.ts +2 -0
  110. package/dist/test/SearchTokenizer.test.d.ts.map +1 -0
  111. package/dist/test/SearchTokenizer.test.js +64 -0
  112. package/dist/test/SearchTokenizer.test.js.map +1 -0
  113. package/dist/test/reusable/CascadeDeleteTests.js +2 -2
  114. package/dist/test/reusable/CascadeDeleteTests.js.map +1 -1
  115. package/dist/test/reusable/ColumnTypesTests.js +2 -2
  116. package/dist/test/reusable/ColumnTypesTests.js.map +1 -1
  117. package/dist/test/reusable/CrudTests.js +2 -2
  118. package/dist/test/reusable/CrudTests.js.map +1 -1
  119. package/dist/test/reusable/DynamicReferenceColumnTests.js +2 -2
  120. package/dist/test/reusable/DynamicReferenceColumnTests.js.map +1 -1
  121. package/dist/test/reusable/PreloadReferencesTests.js +2 -2
  122. package/dist/test/reusable/PreloadReferencesTests.js.map +1 -1
  123. package/dist/test/reusable/RecordIteratorTests.js +2 -2
  124. package/dist/test/reusable/RecordIteratorTests.js.map +1 -1
  125. package/dist/test/reusable/TableManagerTests.js +2 -2
  126. package/dist/test/reusable/TableManagerTests.js.map +1 -1
  127. package/dist/test/reusable/TransactionTests.js +2 -2
  128. package/dist/test/reusable/TransactionTests.js.map +1 -1
  129. package/generated/index.ts +7 -1
  130. package/generated/test/index.ts +7 -1
  131. package/index.ts +16 -0
  132. package/package.json +3 -3
  133. package/src/Columns.ts +6 -2
  134. package/src/Db.ts +137 -12
  135. package/src/Record.ts +21 -4
  136. package/src/Table.ts +109 -2
  137. package/src/TableQueryTransformProvider.ts +31 -0
  138. package/src/encryption/Base64Url.ts +14 -0
  139. package/src/encryption/DataEncryptionKeyTable.ts +40 -0
  140. package/src/encryption/DataKeyStore.ts +305 -0
  141. package/src/encryption/DbEncryptionConfig.ts +92 -0
  142. package/src/encryption/EncryptedColumnQueryError.ts +15 -0
  143. package/src/encryption/EncryptedColumnQueryTransform.ts +383 -0
  144. package/src/encryption/EncryptedColumns.ts +318 -0
  145. package/src/encryption/EncryptionDerivedTableRegistry.ts +34 -0
  146. package/src/encryption/EncryptionEnvelope.ts +60 -0
  147. package/src/encryption/EncryptionLifecycleWalker.ts +243 -0
  148. package/src/encryption/EncryptionRecordHooks.ts +167 -0
  149. package/src/encryption/EncryptionTokenMaintenance.ts +123 -0
  150. package/src/encryption/InMemoryMasterKeyProvider.ts +42 -0
  151. package/src/encryption/MasterKeyProvider.ts +26 -0
  152. package/src/encryption/SearchTokenizer.ts +103 -0
  153. package/src/schema/TableManager.ts +43 -1
  154. package/test/EncryptedColumnsSchema.test.ts +172 -0
  155. package/test/EncryptionEnvelope.test.ts +66 -0
  156. package/test/EncryptionQueryContract.test.ts +195 -0
  157. package/test/SearchTokenizer.test.ts +67 -0
  158. package/test/reusable/CascadeDeleteTests.ts +2 -2
  159. package/test/reusable/ColumnTypesTests.ts +2 -2
  160. package/test/reusable/CrudTests.ts +2 -2
  161. package/test/reusable/DynamicReferenceColumnTests.ts +2 -2
  162. package/test/reusable/PreloadReferencesTests.ts +2 -2
  163. package/test/reusable/RecordIteratorTests.ts +2 -2
  164. package/test/reusable/TableManagerTests.ts +2 -2
  165. package/test/reusable/TransactionTests.ts +2 -2
@@ -0,0 +1,33 @@
1
+ import { Table } from '../Table';
2
+ import { Record } from '../Record';
3
+ /**
4
+ * One wrapped per-owner data key version (see `DataKeyStore`).
5
+ *
6
+ * - `active` — encrypts new writes (the highest active version) and fingerprints queries.
7
+ * - `retired` — decrypt-only: envelopes referencing it still unwrap, but no new writes or
8
+ * query fingerprints use it. A rotation walk moves every row off a version, then retires it.
9
+ *
10
+ * Crypto-shred = deleting an owner's rows here: every envelope naming that owner becomes
11
+ * permanently unreadable, including inside backups.
12
+ */
13
+ export interface DataEncryptionKey extends Record {
14
+ /** The key owner (a user id — the row's permission-source scope owner). */
15
+ owner: string;
16
+ /** Monotonic per-owner version; envelopes name (owner, version). */
17
+ version: number;
18
+ /** The data-key material, wrapped by the master key (`MasterKeyProvider`). */
19
+ wrappedKey: string;
20
+ status: 'active' | 'retired';
21
+ }
22
+ export declare class DataEncryptionKeyTable extends Table<DataEncryptionKey> {
23
+ name: string;
24
+ columns: Table<DataEncryptionKey>['columns'];
25
+ /** (owner, version) is the identity an envelope names — the race loser on concurrent
26
+ * first-write key creation fails here and re-reads the winner's key. */
27
+ indexes: {
28
+ columns: (keyof DataEncryptionKey)[];
29
+ name?: string;
30
+ unique?: boolean;
31
+ }[];
32
+ }
33
+ //# sourceMappingURL=DataEncryptionKeyTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataEncryptionKeyTable.d.ts","sourceRoot":"","sources":["../../../src/encryption/DataEncryptionKeyTable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,MAAM,EAAqB,MAAM,WAAW,CAAC;AAGtD;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAkB,SAAQ,MAAM;IAC/C,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC9B;AAED,qBAAa,sBAAuB,SAAQ,KAAK,CAAC,iBAAiB,CAAC;IAC3D,IAAI,SAAyB;IAC7B,OAAO,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC,SAAS,CAAC,CAKhD;IACH;6EACyE;IAClE,OAAO,EAAE;QAAE,OAAO,EAAE,CAAC,MAAM,iBAAiB,CAAC,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAEzF;CAGH"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.DataEncryptionKeyTable = void 0;
19
+ var Table_1 = require("../Table");
20
+ var Record_1 = require("../Record");
21
+ var Columns_1 = require("../Columns");
22
+ var DataEncryptionKeyTable = /** @class */ (function (_super) {
23
+ __extends(DataEncryptionKeyTable, _super);
24
+ function DataEncryptionKeyTable() {
25
+ var _this = _super !== null && _super.apply(this, arguments) || this;
26
+ _this.name = 'data_encryption_key';
27
+ _this.columns = (0, Record_1.withRecordColumns)({
28
+ owner: new Columns_1.StringColumn('owner', { nullable: false }, 36),
29
+ version: new Columns_1.IntegerColumn('version', { nullable: false }),
30
+ wrappedKey: new Columns_1.StringColumn('wrapped_key', { nullable: false }, 'MAX'),
31
+ status: new Columns_1.StringColumn('status', { nullable: false }, 16),
32
+ });
33
+ /** (owner, version) is the identity an envelope names — the race loser on concurrent
34
+ * first-write key creation fails here and re-reads the winner's key. */
35
+ _this.indexes = [
36
+ { columns: ['owner', 'version'], name: 'data_encryption_key_owner_version_unique', unique: true },
37
+ ];
38
+ return _this;
39
+ // No auth block: default-deny for every non-system caller. Key rows are framework
40
+ // machinery, only ever touched through system paths (DataKeyStore).
41
+ }
42
+ return DataEncryptionKeyTable;
43
+ }(Table_1.Table));
44
+ exports.DataEncryptionKeyTable = DataEncryptionKeyTable;
45
+ //# sourceMappingURL=DataEncryptionKeyTable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataEncryptionKeyTable.js","sourceRoot":"","sources":["../../../src/encryption/DataEncryptionKeyTable.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,kCAAiC;AACjC,oCAAsD;AACtD,sCAAyD;AAsBzD;IAA4C,0CAAwB;IAApE;QAAA,qEAeC;QAdQ,UAAI,GAAG,qBAAqB,CAAC;QAC7B,aAAO,GAAwC,IAAA,0BAAiB,EAAoB;YACzF,KAAK,EAAE,IAAI,sBAAY,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;YACzD,OAAO,EAAE,IAAI,uBAAa,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YAC1D,UAAU,EAAE,IAAI,sBAAY,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,CAAC;YACvE,MAAM,EAAE,IAAI,sBAAY,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;SAC5D,CAAC,CAAC;QACH;iFACyE;QAClE,aAAO,GAAgF;YAC5F,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,0CAA0C,EAAE,MAAM,EAAE,IAAI,EAAE;SAClG,CAAC;;QACF,kFAAkF;QAClF,oEAAoE;IACtE,CAAC;IAAD,6BAAC;AAAD,CAAC,AAfD,CAA4C,aAAK,GAehD;AAfY,wDAAsB"}
@@ -0,0 +1,84 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ /**
4
+ * Decrypt was asked for a key that does not exist — most often because the owner's keys were
5
+ * crypto-shredded (account deletion): the ciphertext is permanently unreadable, by design.
6
+ */
7
+ export declare class EncryptionKeyUnavailableError extends Error {
8
+ constructor(owner: string, version: number);
9
+ }
10
+ /** Unwrapped material of one data-key version. */
11
+ export interface DataKeyMaterial {
12
+ owner: string;
13
+ version: number;
14
+ /** AES-256 key for row values (first half of the 64-byte material). */
15
+ cipherKey: Buffer;
16
+ /** HMAC key for search-token fingerprints (second half). */
17
+ indexKey: Buffer;
18
+ }
19
+ /**
20
+ * Per-owner data keys for column encryption: creation, unwrap-once caching, rotation,
21
+ * retirement, and crypto-shred. Key rows live in `DataEncryptionKeyTable`, wrapped by the
22
+ * deployment's `MasterKeyProvider`; the vault is called once per key (then cached), never
23
+ * per row.
24
+ *
25
+ * All database access runs as system, OUTSIDE any ambient transaction: a key row must be
26
+ * durable independent of the caller's transaction outcome, because unwrapped material is
27
+ * cached in-process the moment it exists — a key created inside a transaction that later
28
+ * rolls back would leave the cache claiming a key the database lost. An orphaned key row
29
+ * from a rolled-back first write is harmless (a key no envelope names).
30
+ *
31
+ * The caches live on the global object (the per-package-install duplicate-module pattern —
32
+ * see `Db.getDefaultDbDriver`), so every live copy of this package shares one cache.
33
+ */
34
+ export declare class DataKeyStore {
35
+ /** Unwrapped material cache TTL — bounds how long a shredded key can linger in a warm process. */
36
+ private static readonly MATERIAL_TTL_MS;
37
+ /** Owner key-row list TTL — bounds cross-process staleness of the active-version set. */
38
+ private static readonly OWNER_ROWS_TTL_MS;
39
+ private static readonly CACHES_GLOBAL_KEY;
40
+ private static readonly KEY_MATERIAL_BYTES;
41
+ private logger;
42
+ private table;
43
+ /**
44
+ * The key that encrypts new writes for `owner`: the highest active version, created on
45
+ * first use (each owner gets a randomly generated data key, wrapped by the master key).
46
+ */
47
+ getWriteKey(owner: string): Promise<DataKeyMaterial>;
48
+ /** The key an envelope names — any status; decrypt must work until the key is shredded. */
49
+ getKeyByVersion(owner: string, version: number): Promise<DataKeyMaterial>;
50
+ /**
51
+ * The index keys a query fingerprints with: every ACTIVE version of every accessible
52
+ * owner (normally one per owner; two during a rotation window). Owners with no keys yet
53
+ * contribute nothing — they cannot have encrypted rows.
54
+ */
55
+ getQueryIndexKeys(owners: string[]): Promise<DataKeyMaterial[]>;
56
+ /**
57
+ * Mint the next key version for `owner` (new writes use it immediately; the old version
58
+ * stays active — still fingerprinting queries — until a rotation walk
59
+ * (`EncryptionLifecycleWalker` mode 'rotate-keys') has rewritten every row, after which
60
+ * the caller retires it via `retireKeyVersion`).
61
+ * @returns the new version number
62
+ */
63
+ rotateKey(owner: string): Promise<number>;
64
+ /** Retire a version: envelopes naming it still decrypt; queries and writes stop using it. */
65
+ retireKeyVersion(owner: string, version: number): Promise<void>;
66
+ /**
67
+ * Crypto-shred: delete every key version of `owner` and evict the caches. Every envelope
68
+ * naming the owner — in live rows and in every backup — becomes permanently unreadable.
69
+ */
70
+ shredOwnerKeys(owner: string): Promise<number>;
71
+ private createKeyVersion;
72
+ private getOwnerRows;
73
+ private unwrap;
74
+ private highestActive;
75
+ private requireOwner;
76
+ /**
77
+ * A system Db pinned OUTSIDE any ambient transaction (see class doc). Imported lazily —
78
+ * this module is reachable from the serializer layer, below `Db` in the module graph.
79
+ */
80
+ private systemDb;
81
+ private caches;
82
+ private evictOwner;
83
+ }
84
+ //# sourceMappingURL=DataKeyStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataKeyStore.d.ts","sourceRoot":"","sources":["../../../src/encryption/DataKeyStore.ts"],"names":[],"mappings":";;AAKA;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAQ3C;AAED,kDAAkD;AAClD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAiBD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAY;IACvB,kGAAkG;IAClG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAkB;IACzD,yFAAyF;IACzF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAa;IACtD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAkC;IAC3E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAM;IAChD,OAAO,CAAC,MAAM,CAA+C;IAC7D,OAAO,CAAC,KAAK,CAAgC;IAE7C;;;OAGG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAiB1D,2FAA2F;IACrF,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAkB/E;;;;OAIG;IACG,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAcrE;;;;;;OAMG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAU/C,6FAA6F;IACvF,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAarE;;;OAGG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAetC,gBAAgB;YAsBhB,YAAY;YAsBZ,MAAM;IA2BpB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,YAAY;IAMpB;;;OAGG;YACW,QAAQ;IAuBtB,OAAO,CAAC,MAAM;IAYd,OAAO,CAAC,UAAU;CAGnB"}
@@ -0,0 +1,481 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
41
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
42
+ return new (P || (P = Promise))(function (resolve, reject) {
43
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
44
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
45
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
46
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
47
+ });
48
+ };
49
+ var __generator = (this && this.__generator) || function (thisArg, body) {
50
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
51
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
52
+ function verb(n) { return function (v) { return step([n, v]); }; }
53
+ function step(op) {
54
+ if (f) throw new TypeError("Generator is already executing.");
55
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
56
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
57
+ if (y = 0, t) op = [op[0] & 2, t.value];
58
+ switch (op[0]) {
59
+ case 0: case 1: t = op; break;
60
+ case 4: _.label++; return { value: op[1], done: false };
61
+ case 5: _.label++; y = op[1]; op = [0]; continue;
62
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
63
+ default:
64
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
65
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
66
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
67
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
68
+ if (t[2]) _.ops.pop();
69
+ _.trys.pop(); continue;
70
+ }
71
+ op = body.call(thisArg, _);
72
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
73
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
74
+ }
75
+ };
76
+ Object.defineProperty(exports, "__esModule", { value: true });
77
+ exports.DataKeyStore = exports.EncryptionKeyUnavailableError = void 0;
78
+ var crypto_1 = require("crypto");
79
+ var logger_1 = require("@proteinjs/logger");
80
+ var DbEncryptionConfig_1 = require("./DbEncryptionConfig");
81
+ var DataEncryptionKeyTable_1 = require("./DataEncryptionKeyTable");
82
+ /**
83
+ * Decrypt was asked for a key that does not exist — most often because the owner's keys were
84
+ * crypto-shredded (account deletion): the ciphertext is permanently unreadable, by design.
85
+ */
86
+ var EncryptionKeyUnavailableError = /** @class */ (function (_super) {
87
+ __extends(EncryptionKeyUnavailableError, _super);
88
+ function EncryptionKeyUnavailableError(owner, version) {
89
+ var _this = _super.call(this, "No data key exists for owner '".concat(owner, "' version ").concat(version, ". If the owner's keys were ") +
90
+ "deleted (crypto-shred), rows encrypted under them are permanently unreadable.") || this;
91
+ _this.name = 'EncryptionKeyUnavailableError';
92
+ Object.setPrototypeOf(_this, EncryptionKeyUnavailableError.prototype);
93
+ return _this;
94
+ }
95
+ return EncryptionKeyUnavailableError;
96
+ }(Error));
97
+ exports.EncryptionKeyUnavailableError = EncryptionKeyUnavailableError;
98
+ /**
99
+ * Per-owner data keys for column encryption: creation, unwrap-once caching, rotation,
100
+ * retirement, and crypto-shred. Key rows live in `DataEncryptionKeyTable`, wrapped by the
101
+ * deployment's `MasterKeyProvider`; the vault is called once per key (then cached), never
102
+ * per row.
103
+ *
104
+ * All database access runs as system, OUTSIDE any ambient transaction: a key row must be
105
+ * durable independent of the caller's transaction outcome, because unwrapped material is
106
+ * cached in-process the moment it exists — a key created inside a transaction that later
107
+ * rolls back would leave the cache claiming a key the database lost. An orphaned key row
108
+ * from a rolled-back first write is harmless (a key no envelope names).
109
+ *
110
+ * The caches live on the global object (the per-package-install duplicate-module pattern —
111
+ * see `Db.getDefaultDbDriver`), so every live copy of this package shares one cache.
112
+ */
113
+ var DataKeyStore = /** @class */ (function () {
114
+ function DataKeyStore() {
115
+ this.logger = new logger_1.Logger({ name: this.constructor.name });
116
+ this.table = new DataEncryptionKeyTable_1.DataEncryptionKeyTable();
117
+ }
118
+ /**
119
+ * The key that encrypts new writes for `owner`: the highest active version, created on
120
+ * first use (each owner gets a randomly generated data key, wrapped by the master key).
121
+ */
122
+ DataKeyStore.prototype.getWriteKey = function (owner) {
123
+ return __awaiter(this, void 0, void 0, function () {
124
+ var rows, active;
125
+ return __generator(this, function (_a) {
126
+ switch (_a.label) {
127
+ case 0:
128
+ this.requireOwner(owner);
129
+ return [4 /*yield*/, this.getOwnerRows(owner)];
130
+ case 1:
131
+ rows = _a.sent();
132
+ active = this.highestActive(rows);
133
+ if (!!active) return [3 /*break*/, 4];
134
+ return [4 /*yield*/, this.createKeyVersion(owner, 1)];
135
+ case 2:
136
+ _a.sent();
137
+ this.evictOwner(owner);
138
+ return [4 /*yield*/, this.getOwnerRows(owner)];
139
+ case 3:
140
+ rows = _a.sent();
141
+ active = this.highestActive(rows);
142
+ if (!active) {
143
+ throw new EncryptionKeyUnavailableError(owner, 1);
144
+ }
145
+ _a.label = 4;
146
+ case 4: return [4 /*yield*/, this.unwrap(active)];
147
+ case 5: return [2 /*return*/, _a.sent()];
148
+ }
149
+ });
150
+ });
151
+ };
152
+ /** The key an envelope names — any status; decrypt must work until the key is shredded. */
153
+ DataKeyStore.prototype.getKeyByVersion = function (owner, version) {
154
+ return __awaiter(this, void 0, void 0, function () {
155
+ var rows, row, freshRows, freshRow;
156
+ return __generator(this, function (_a) {
157
+ switch (_a.label) {
158
+ case 0: return [4 /*yield*/, this.getOwnerRows(owner)];
159
+ case 1:
160
+ rows = _a.sent();
161
+ row = rows.find(function (candidate) { return candidate.version === version; });
162
+ if (!!row) return [3 /*break*/, 4];
163
+ // The row list may be cached from before this version existed (e.g. a fresh rotation
164
+ // in another process) — refresh once before declaring the key gone.
165
+ this.evictOwner(owner);
166
+ return [4 /*yield*/, this.getOwnerRows(owner)];
167
+ case 2:
168
+ freshRows = _a.sent();
169
+ freshRow = freshRows.find(function (candidate) { return candidate.version === version; });
170
+ if (!freshRow) {
171
+ throw new EncryptionKeyUnavailableError(owner, version);
172
+ }
173
+ return [4 /*yield*/, this.unwrap(freshRow)];
174
+ case 3: return [2 /*return*/, _a.sent()];
175
+ case 4: return [4 /*yield*/, this.unwrap(row)];
176
+ case 5: return [2 /*return*/, _a.sent()];
177
+ }
178
+ });
179
+ });
180
+ };
181
+ /**
182
+ * The index keys a query fingerprints with: every ACTIVE version of every accessible
183
+ * owner (normally one per owner; two during a rotation window). Owners with no keys yet
184
+ * contribute nothing — they cannot have encrypted rows.
185
+ */
186
+ DataKeyStore.prototype.getQueryIndexKeys = function (owners) {
187
+ return __awaiter(this, void 0, void 0, function () {
188
+ var keys, _i, owners_1, owner, rows, _a, rows_1, row, _b, _c;
189
+ return __generator(this, function (_d) {
190
+ switch (_d.label) {
191
+ case 0:
192
+ keys = [];
193
+ _i = 0, owners_1 = owners;
194
+ _d.label = 1;
195
+ case 1:
196
+ if (!(_i < owners_1.length)) return [3 /*break*/, 7];
197
+ owner = owners_1[_i];
198
+ return [4 /*yield*/, this.getOwnerRows(owner)];
199
+ case 2:
200
+ rows = _d.sent();
201
+ _a = 0, rows_1 = rows;
202
+ _d.label = 3;
203
+ case 3:
204
+ if (!(_a < rows_1.length)) return [3 /*break*/, 6];
205
+ row = rows_1[_a];
206
+ if (!(row.status === 'active')) return [3 /*break*/, 5];
207
+ _c = (_b = keys).push;
208
+ return [4 /*yield*/, this.unwrap(row)];
209
+ case 4:
210
+ _c.apply(_b, [_d.sent()]);
211
+ _d.label = 5;
212
+ case 5:
213
+ _a++;
214
+ return [3 /*break*/, 3];
215
+ case 6:
216
+ _i++;
217
+ return [3 /*break*/, 1];
218
+ case 7: return [2 /*return*/, keys];
219
+ }
220
+ });
221
+ });
222
+ };
223
+ /**
224
+ * Mint the next key version for `owner` (new writes use it immediately; the old version
225
+ * stays active — still fingerprinting queries — until a rotation walk
226
+ * (`EncryptionLifecycleWalker` mode 'rotate-keys') has rewritten every row, after which
227
+ * the caller retires it via `retireKeyVersion`).
228
+ * @returns the new version number
229
+ */
230
+ DataKeyStore.prototype.rotateKey = function (owner) {
231
+ return __awaiter(this, void 0, void 0, function () {
232
+ var rows, highest, newVersion;
233
+ return __generator(this, function (_a) {
234
+ switch (_a.label) {
235
+ case 0:
236
+ this.requireOwner(owner);
237
+ return [4 /*yield*/, this.getOwnerRows(owner)];
238
+ case 1:
239
+ rows = _a.sent();
240
+ highest = rows.reduce(function (max, row) { return Math.max(max, row.version); }, 0);
241
+ newVersion = highest + 1;
242
+ return [4 /*yield*/, this.createKeyVersion(owner, newVersion)];
243
+ case 2:
244
+ _a.sent();
245
+ this.evictOwner(owner);
246
+ return [2 /*return*/, newVersion];
247
+ }
248
+ });
249
+ });
250
+ };
251
+ /** Retire a version: envelopes naming it still decrypt; queries and writes stop using it. */
252
+ DataKeyStore.prototype.retireKeyVersion = function (owner, version) {
253
+ return __awaiter(this, void 0, void 0, function () {
254
+ var db;
255
+ return __generator(this, function (_a) {
256
+ switch (_a.label) {
257
+ case 0: return [4 /*yield*/, this.systemDb()];
258
+ case 1:
259
+ db = _a.sent();
260
+ return [4 /*yield*/, db.update(this.table, { status: 'retired' }, {
261
+ owner: owner,
262
+ version: version,
263
+ })];
264
+ case 2:
265
+ _a.sent();
266
+ this.evictOwner(owner);
267
+ return [2 /*return*/];
268
+ }
269
+ });
270
+ });
271
+ };
272
+ /**
273
+ * Crypto-shred: delete every key version of `owner` and evict the caches. Every envelope
274
+ * naming the owner — in live rows and in every backup — becomes permanently unreadable.
275
+ */
276
+ DataKeyStore.prototype.shredOwnerKeys = function (owner) {
277
+ return __awaiter(this, void 0, void 0, function () {
278
+ var db, deleted, caches, _i, _a, cacheKey;
279
+ return __generator(this, function (_b) {
280
+ switch (_b.label) {
281
+ case 0: return [4 /*yield*/, this.systemDb()];
282
+ case 1:
283
+ db = _b.sent();
284
+ return [4 /*yield*/, db.delete(this.table, { owner: owner })];
285
+ case 2:
286
+ deleted = _b.sent();
287
+ this.evictOwner(owner);
288
+ caches = this.caches();
289
+ for (_i = 0, _a = Array.from(caches.material.keys()); _i < _a.length; _i++) {
290
+ cacheKey = _a[_i];
291
+ if (cacheKey.startsWith("".concat(owner, ":"))) {
292
+ caches.material.delete(cacheKey);
293
+ }
294
+ }
295
+ this.logger.info({ message: "Crypto-shredded data keys", obj: { owner: owner, deleted: deleted } });
296
+ return [2 /*return*/, deleted];
297
+ }
298
+ });
299
+ });
300
+ };
301
+ DataKeyStore.prototype.createKeyVersion = function (owner, version) {
302
+ return __awaiter(this, void 0, void 0, function () {
303
+ var config, material, wrappedKey, db, error_1, rows;
304
+ return __generator(this, function (_a) {
305
+ switch (_a.label) {
306
+ case 0:
307
+ config = (0, DbEncryptionConfig_1.getDbEncryptionConfig)();
308
+ material = (0, crypto_1.randomBytes)(DataKeyStore.KEY_MATERIAL_BYTES);
309
+ return [4 /*yield*/, config.masterKeyProvider.wrapDataKey(material)];
310
+ case 1:
311
+ wrappedKey = _a.sent();
312
+ return [4 /*yield*/, this.systemDb()];
313
+ case 2:
314
+ db = _a.sent();
315
+ _a.label = 3;
316
+ case 3:
317
+ _a.trys.push([3, 5, , 7]);
318
+ return [4 /*yield*/, db.insert(this.table, { owner: owner, version: version, wrappedKey: wrappedKey, status: 'active' })];
319
+ case 4:
320
+ _a.sent();
321
+ return [3 /*break*/, 7];
322
+ case 5:
323
+ error_1 = _a.sent();
324
+ // Named race: two first writes for the same owner both create version 1; the unique
325
+ // (owner, version) index rejects the loser. Re-read — if the winner's key is there,
326
+ // use it; otherwise the failure was real.
327
+ this.evictOwner(owner);
328
+ return [4 /*yield*/, this.getOwnerRows(owner)];
329
+ case 6:
330
+ rows = _a.sent();
331
+ if (!rows.some(function (row) { return row.version === version; })) {
332
+ throw error_1;
333
+ }
334
+ return [3 /*break*/, 7];
335
+ case 7: return [2 /*return*/];
336
+ }
337
+ });
338
+ });
339
+ };
340
+ DataKeyStore.prototype.getOwnerRows = function (owner) {
341
+ return __awaiter(this, void 0, void 0, function () {
342
+ var caches, cached, db, rows, entry;
343
+ return __generator(this, function (_a) {
344
+ switch (_a.label) {
345
+ case 0:
346
+ caches = this.caches();
347
+ cached = caches.ownerRows.get(owner);
348
+ if (cached && Date.now() - cached.fetchedAt < DataKeyStore.OWNER_ROWS_TTL_MS) {
349
+ return [2 /*return*/, cached.rows];
350
+ }
351
+ return [4 /*yield*/, this.systemDb()];
352
+ case 1:
353
+ db = _a.sent();
354
+ return [4 /*yield*/, db.query(this.table, { owner: owner })];
355
+ case 2:
356
+ rows = _a.sent();
357
+ entry = {
358
+ fetchedAt: Date.now(),
359
+ rows: rows.map(function (row) { return ({
360
+ owner: row.owner,
361
+ version: row.version,
362
+ wrappedKey: row.wrappedKey,
363
+ status: row.status,
364
+ }); }),
365
+ };
366
+ caches.ownerRows.set(owner, entry);
367
+ return [2 /*return*/, entry.rows];
368
+ }
369
+ });
370
+ });
371
+ };
372
+ DataKeyStore.prototype.unwrap = function (row) {
373
+ return __awaiter(this, void 0, void 0, function () {
374
+ var caches, cacheKey, cached, config, materialBytes, material;
375
+ return __generator(this, function (_a) {
376
+ switch (_a.label) {
377
+ case 0:
378
+ caches = this.caches();
379
+ cacheKey = "".concat(row.owner, ":").concat(row.version);
380
+ cached = caches.material.get(cacheKey);
381
+ if (cached && Date.now() - cached.cachedAt < DataKeyStore.MATERIAL_TTL_MS) {
382
+ return [2 /*return*/, cached.material];
383
+ }
384
+ config = (0, DbEncryptionConfig_1.getDbEncryptionConfig)();
385
+ return [4 /*yield*/, config.masterKeyProvider.unwrapDataKey(row.wrappedKey)];
386
+ case 1:
387
+ materialBytes = _a.sent();
388
+ if (materialBytes.length !== DataKeyStore.KEY_MATERIAL_BYTES) {
389
+ throw new Error("Data key material for owner '".concat(row.owner, "' version ").concat(row.version, " has unexpected length ") +
390
+ "".concat(materialBytes.length, " (expected ").concat(DataKeyStore.KEY_MATERIAL_BYTES, ") \u2014 wrong master key?"));
391
+ }
392
+ material = {
393
+ owner: row.owner,
394
+ version: row.version,
395
+ cipherKey: materialBytes.subarray(0, 32),
396
+ indexKey: materialBytes.subarray(32, 64),
397
+ };
398
+ caches.material.set(cacheKey, { cachedAt: Date.now(), material: material });
399
+ return [2 /*return*/, material];
400
+ }
401
+ });
402
+ });
403
+ };
404
+ DataKeyStore.prototype.highestActive = function (rows) {
405
+ return rows.filter(function (row) { return row.status === 'active'; }).sort(function (a, b) { return b.version - a.version; })[0];
406
+ };
407
+ DataKeyStore.prototype.requireOwner = function (owner) {
408
+ if (!owner || typeof owner !== 'string') {
409
+ throw new Error("Data key operations require a non-empty owner id; got: ".concat(JSON.stringify(owner)));
410
+ }
411
+ };
412
+ /**
413
+ * A system Db pinned OUTSIDE any ambient transaction (see class doc). Imported lazily —
414
+ * this module is reachable from the serializer layer, below `Db` in the module graph.
415
+ */
416
+ DataKeyStore.prototype.systemDb = function () {
417
+ return __awaiter(this, void 0, void 0, function () {
418
+ var Db, getDefaultTransactionContextFactory, db, factory;
419
+ return __generator(this, function (_a) {
420
+ switch (_a.label) {
421
+ case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require('../Db')); })];
422
+ case 1:
423
+ Db = (_a.sent()).Db;
424
+ return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require('../transaction/TransactionContextFactory')); })];
425
+ case 2:
426
+ getDefaultTransactionContextFactory = (_a.sent()).getDefaultTransactionContextFactory;
427
+ db = new Db(undefined, undefined, undefined, true);
428
+ factory = getDefaultTransactionContextFactory();
429
+ if (!factory) {
430
+ return [2 /*return*/, db];
431
+ }
432
+ // Proxy every operation through an empty transaction context so key-table IO
433
+ // auto-commits even when the caller is mid-transaction.
434
+ return [2 /*return*/, new Proxy(db, {
435
+ get: function (target, prop, receiver) {
436
+ var _this = this;
437
+ var value = Reflect.get(target, prop, receiver);
438
+ if (typeof value !== 'function') {
439
+ return value;
440
+ }
441
+ return function () {
442
+ var args = [];
443
+ for (var _i = 0; _i < arguments.length; _i++) {
444
+ args[_i] = arguments[_i];
445
+ }
446
+ return factory.runInContext({}, function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
447
+ switch (_a.label) {
448
+ case 0: return [4 /*yield*/, value.apply(target, args)];
449
+ case 1: return [2 /*return*/, _a.sent()];
450
+ }
451
+ }); }); });
452
+ };
453
+ },
454
+ })];
455
+ }
456
+ });
457
+ });
458
+ };
459
+ DataKeyStore.prototype.caches = function () {
460
+ var globalObject = globalThis;
461
+ if (!globalObject[DataKeyStore.CACHES_GLOBAL_KEY]) {
462
+ globalObject[DataKeyStore.CACHES_GLOBAL_KEY] = {
463
+ ownerRows: new Map(),
464
+ material: new Map(),
465
+ };
466
+ }
467
+ return globalObject[DataKeyStore.CACHES_GLOBAL_KEY];
468
+ };
469
+ DataKeyStore.prototype.evictOwner = function (owner) {
470
+ this.caches().ownerRows.delete(owner);
471
+ };
472
+ /** Unwrapped material cache TTL — bounds how long a shredded key can linger in a warm process. */
473
+ DataKeyStore.MATERIAL_TTL_MS = 10 * 60 * 1000;
474
+ /** Owner key-row list TTL — bounds cross-process staleness of the active-version set. */
475
+ DataKeyStore.OWNER_ROWS_TTL_MS = 60 * 1000;
476
+ DataKeyStore.CACHES_GLOBAL_KEY = '__proteinjs_db_dataKeyCaches';
477
+ DataKeyStore.KEY_MATERIAL_BYTES = 64;
478
+ return DataKeyStore;
479
+ }());
480
+ exports.DataKeyStore = DataKeyStore;
481
+ //# sourceMappingURL=DataKeyStore.js.map