@proteinjs/db 1.35.1 → 1.36.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 (160) hide show
  1. package/CHANGELOG.md +11 -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/Db.d.ts +25 -0
  13. package/dist/src/Db.d.ts.map +1 -1
  14. package/dist/src/Db.js +219 -22
  15. package/dist/src/Db.js.map +1 -1
  16. package/dist/src/Record.d.ts +7 -1
  17. package/dist/src/Record.d.ts.map +1 -1
  18. package/dist/src/Record.js +56 -21
  19. package/dist/src/Record.js.map +1 -1
  20. package/dist/src/Table.d.ts +82 -1
  21. package/dist/src/Table.d.ts.map +1 -1
  22. package/dist/src/Table.js +24 -1
  23. package/dist/src/Table.js.map +1 -1
  24. package/dist/src/TableQueryTransformProvider.d.ts +17 -0
  25. package/dist/src/TableQueryTransformProvider.d.ts.map +1 -0
  26. package/dist/src/TableQueryTransformProvider.js +34 -0
  27. package/dist/src/TableQueryTransformProvider.js.map +1 -0
  28. package/dist/src/encryption/Base64Url.d.ts +12 -0
  29. package/dist/src/encryption/Base64Url.d.ts.map +1 -0
  30. package/dist/src/encryption/Base64Url.js +21 -0
  31. package/dist/src/encryption/Base64Url.js.map +1 -0
  32. package/dist/src/encryption/DataEncryptionKeyTable.d.ts +33 -0
  33. package/dist/src/encryption/DataEncryptionKeyTable.d.ts.map +1 -0
  34. package/dist/src/encryption/DataEncryptionKeyTable.js +45 -0
  35. package/dist/src/encryption/DataEncryptionKeyTable.js.map +1 -0
  36. package/dist/src/encryption/DataKeyStore.d.ts +84 -0
  37. package/dist/src/encryption/DataKeyStore.d.ts.map +1 -0
  38. package/dist/src/encryption/DataKeyStore.js +481 -0
  39. package/dist/src/encryption/DataKeyStore.js.map +1 -0
  40. package/dist/src/encryption/DbEncryptionConfig.d.ts +62 -0
  41. package/dist/src/encryption/DbEncryptionConfig.d.ts.map +1 -0
  42. package/dist/src/encryption/DbEncryptionConfig.js +67 -0
  43. package/dist/src/encryption/DbEncryptionConfig.js.map +1 -0
  44. package/dist/src/encryption/EncryptedColumnQueryError.d.ts +10 -0
  45. package/dist/src/encryption/EncryptedColumnQueryError.d.ts.map +1 -0
  46. package/dist/src/encryption/EncryptedColumnQueryError.js +38 -0
  47. package/dist/src/encryption/EncryptedColumnQueryError.js.map +1 -0
  48. package/dist/src/encryption/EncryptedColumnQueryTransform.d.ts +52 -0
  49. package/dist/src/encryption/EncryptedColumnQueryTransform.d.ts.map +1 -0
  50. package/dist/src/encryption/EncryptedColumnQueryTransform.js +423 -0
  51. package/dist/src/encryption/EncryptedColumnQueryTransform.js.map +1 -0
  52. package/dist/src/encryption/EncryptedColumns.d.ts +69 -0
  53. package/dist/src/encryption/EncryptedColumns.d.ts.map +1 -0
  54. package/dist/src/encryption/EncryptedColumns.js +286 -0
  55. package/dist/src/encryption/EncryptedColumns.js.map +1 -0
  56. package/dist/src/encryption/EncryptionDerivedTableRegistry.d.ts +20 -0
  57. package/dist/src/encryption/EncryptionDerivedTableRegistry.d.ts.map +1 -0
  58. package/dist/src/encryption/EncryptionDerivedTableRegistry.js +36 -0
  59. package/dist/src/encryption/EncryptionDerivedTableRegistry.js.map +1 -0
  60. package/dist/src/encryption/EncryptionEnvelope.d.ts +25 -0
  61. package/dist/src/encryption/EncryptionEnvelope.d.ts.map +1 -0
  62. package/dist/src/encryption/EncryptionEnvelope.js +59 -0
  63. package/dist/src/encryption/EncryptionEnvelope.js.map +1 -0
  64. package/dist/src/encryption/EncryptionLifecycleWalker.d.ts +65 -0
  65. package/dist/src/encryption/EncryptionLifecycleWalker.d.ts.map +1 -0
  66. package/dist/src/encryption/EncryptionLifecycleWalker.js +343 -0
  67. package/dist/src/encryption/EncryptionLifecycleWalker.js.map +1 -0
  68. package/dist/src/encryption/EncryptionRecordHooks.d.ts +47 -0
  69. package/dist/src/encryption/EncryptionRecordHooks.d.ts.map +1 -0
  70. package/dist/src/encryption/EncryptionRecordHooks.js +229 -0
  71. package/dist/src/encryption/EncryptionRecordHooks.js.map +1 -0
  72. package/dist/src/encryption/EncryptionTokenMaintenance.d.ts +34 -0
  73. package/dist/src/encryption/EncryptionTokenMaintenance.d.ts.map +1 -0
  74. package/dist/src/encryption/EncryptionTokenMaintenance.js +211 -0
  75. package/dist/src/encryption/EncryptionTokenMaintenance.js.map +1 -0
  76. package/dist/src/encryption/InMemoryMasterKeyProvider.d.ts +20 -0
  77. package/dist/src/encryption/InMemoryMasterKeyProvider.d.ts.map +1 -0
  78. package/dist/src/encryption/InMemoryMasterKeyProvider.js +87 -0
  79. package/dist/src/encryption/InMemoryMasterKeyProvider.js.map +1 -0
  80. package/dist/src/encryption/MasterKeyProvider.d.ts +27 -0
  81. package/dist/src/encryption/MasterKeyProvider.d.ts.map +1 -0
  82. package/dist/src/encryption/MasterKeyProvider.js +3 -0
  83. package/dist/src/encryption/MasterKeyProvider.js.map +1 -0
  84. package/dist/src/encryption/SearchTokenizer.d.ts +49 -0
  85. package/dist/src/encryption/SearchTokenizer.d.ts.map +1 -0
  86. package/dist/src/encryption/SearchTokenizer.js +106 -0
  87. package/dist/src/encryption/SearchTokenizer.js.map +1 -0
  88. package/dist/src/schema/TableManager.d.ts +10 -0
  89. package/dist/src/schema/TableManager.d.ts.map +1 -1
  90. package/dist/src/schema/TableManager.js +62 -5
  91. package/dist/src/schema/TableManager.js.map +1 -1
  92. package/dist/src/tables/MigrationTable.d.ts +2 -2
  93. package/dist/test/EncryptedColumnsSchema.test.d.ts +2 -0
  94. package/dist/test/EncryptedColumnsSchema.test.d.ts.map +1 -0
  95. package/dist/test/EncryptedColumnsSchema.test.js +151 -0
  96. package/dist/test/EncryptedColumnsSchema.test.js.map +1 -0
  97. package/dist/test/EncryptionEnvelope.test.d.ts +2 -0
  98. package/dist/test/EncryptionEnvelope.test.d.ts.map +1 -0
  99. package/dist/test/EncryptionEnvelope.test.js +109 -0
  100. package/dist/test/EncryptionEnvelope.test.js.map +1 -0
  101. package/dist/test/EncryptionQueryContract.test.d.ts +2 -0
  102. package/dist/test/EncryptionQueryContract.test.d.ts.map +1 -0
  103. package/dist/test/EncryptionQueryContract.test.js +399 -0
  104. package/dist/test/EncryptionQueryContract.test.js.map +1 -0
  105. package/dist/test/SearchTokenizer.test.d.ts +2 -0
  106. package/dist/test/SearchTokenizer.test.d.ts.map +1 -0
  107. package/dist/test/SearchTokenizer.test.js +64 -0
  108. package/dist/test/SearchTokenizer.test.js.map +1 -0
  109. package/dist/test/reusable/CascadeDeleteTests.js +2 -2
  110. package/dist/test/reusable/CascadeDeleteTests.js.map +1 -1
  111. package/dist/test/reusable/ColumnTypesTests.js +2 -2
  112. package/dist/test/reusable/ColumnTypesTests.js.map +1 -1
  113. package/dist/test/reusable/CrudTests.js +2 -2
  114. package/dist/test/reusable/CrudTests.js.map +1 -1
  115. package/dist/test/reusable/DynamicReferenceColumnTests.js +2 -2
  116. package/dist/test/reusable/DynamicReferenceColumnTests.js.map +1 -1
  117. package/dist/test/reusable/PreloadReferencesTests.js +2 -2
  118. package/dist/test/reusable/PreloadReferencesTests.js.map +1 -1
  119. package/dist/test/reusable/RecordIteratorTests.js +2 -2
  120. package/dist/test/reusable/RecordIteratorTests.js.map +1 -1
  121. package/dist/test/reusable/TableManagerTests.js +2 -2
  122. package/dist/test/reusable/TableManagerTests.js.map +1 -1
  123. package/dist/test/reusable/TransactionTests.js +2 -2
  124. package/dist/test/reusable/TransactionTests.js.map +1 -1
  125. package/generated/index.ts +7 -1
  126. package/generated/test/index.ts +7 -1
  127. package/index.ts +16 -0
  128. package/package.json +3 -3
  129. package/src/Db.ts +137 -12
  130. package/src/Record.ts +21 -4
  131. package/src/Table.ts +109 -2
  132. package/src/TableQueryTransformProvider.ts +31 -0
  133. package/src/encryption/Base64Url.ts +14 -0
  134. package/src/encryption/DataEncryptionKeyTable.ts +40 -0
  135. package/src/encryption/DataKeyStore.ts +305 -0
  136. package/src/encryption/DbEncryptionConfig.ts +92 -0
  137. package/src/encryption/EncryptedColumnQueryError.ts +15 -0
  138. package/src/encryption/EncryptedColumnQueryTransform.ts +383 -0
  139. package/src/encryption/EncryptedColumns.ts +318 -0
  140. package/src/encryption/EncryptionDerivedTableRegistry.ts +34 -0
  141. package/src/encryption/EncryptionEnvelope.ts +60 -0
  142. package/src/encryption/EncryptionLifecycleWalker.ts +243 -0
  143. package/src/encryption/EncryptionRecordHooks.ts +167 -0
  144. package/src/encryption/EncryptionTokenMaintenance.ts +123 -0
  145. package/src/encryption/InMemoryMasterKeyProvider.ts +42 -0
  146. package/src/encryption/MasterKeyProvider.ts +26 -0
  147. package/src/encryption/SearchTokenizer.ts +103 -0
  148. package/src/schema/TableManager.ts +43 -1
  149. package/test/EncryptedColumnsSchema.test.ts +172 -0
  150. package/test/EncryptionEnvelope.test.ts +66 -0
  151. package/test/EncryptionQueryContract.test.ts +195 -0
  152. package/test/SearchTokenizer.test.ts +67 -0
  153. package/test/reusable/CascadeDeleteTests.ts +2 -2
  154. package/test/reusable/ColumnTypesTests.ts +2 -2
  155. package/test/reusable/CrudTests.ts +2 -2
  156. package/test/reusable/DynamicReferenceColumnTests.ts +2 -2
  157. package/test/reusable/PreloadReferencesTests.ts +2 -2
  158. package/test/reusable/RecordIteratorTests.ts +2 -2
  159. package/test/reusable/TableManagerTests.ts +2 -2
  160. package/test/reusable/TransactionTests.ts +2 -2
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataKeyStore.js","sourceRoot":"","sources":["../../../src/encryption/DataKeyStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import { Loadable } from '@proteinjs/reflection';
2
+ import type { Table } from '../Table';
3
+ import { MasterKeyProvider } from './MasterKeyProvider';
4
+ /**
5
+ * A column-encryption configuration problem — a misdeclared column, a missing
6
+ * `DbEncryptionConfigFactory`, an unresolvable key owner. Always a dev-time/boot-time
7
+ * error class, never a data error.
8
+ */
9
+ export declare class EncryptedColumnConfigError extends Error {
10
+ constructor(message: string);
11
+ }
12
+ /**
13
+ * Deployment-level configuration for column encryption (`ColumnOptions.encrypted`).
14
+ * Registered once per app through a `DbEncryptionConfigFactory`; every encrypted read,
15
+ * write, and translated query resolves it through `getDbEncryptionConfig`.
16
+ */
17
+ export interface DbEncryptionConfig {
18
+ /** The vault that wraps/unwraps per-user data keys (see `MasterKeyProvider`). */
19
+ masterKeyProvider: MasterKeyProvider;
20
+ /**
21
+ * Resolve the key-owner id whose data key encrypts a row being written — the row's
22
+ * permission-source scope owner. Return `undefined` to fall through to the framework
23
+ * default (the row's `scope` column value). Consumer layers with richer sharing models
24
+ * (e.g. permission-source trees) supply their scope→owner mapping here; the framework
25
+ * stays generic.
26
+ */
27
+ resolveKeyOwner?: (args: {
28
+ table: Table<any>;
29
+ record: any;
30
+ }) => Promise<string | undefined>;
31
+ /**
32
+ * The key owners whose rows the current caller can read — the caller's own id plus the
33
+ * (bounded) set of owners sharing rows into the caller's view. Search conditions on
34
+ * encrypted columns fingerprint the query once per accessible owner and OR the matches,
35
+ * so this powers shared-scope search. Required for any query that searches an encrypted
36
+ * column; without it such queries are rejected loudly.
37
+ */
38
+ getAccessibleKeyOwners?: (args: {
39
+ runAsSystem: boolean;
40
+ }) => Promise<string[]>;
41
+ /**
42
+ * When true, every text-holding column of every registered table MUST declare
43
+ * `encrypted` (`false` or a config object) — registration fails loudly otherwise
44
+ * (see `EncryptedColumns.validateDeclarations`). Ships default-OFF so existing schemas
45
+ * keep booting; the app-wide declaration sweep turns it on.
46
+ */
47
+ requireEncryptedDeclarations?: boolean;
48
+ }
49
+ /** Registers the app's `DbEncryptionConfig`. Implement as a Loadable so the framework finds it. */
50
+ export interface DbEncryptionConfigFactory extends Loadable {
51
+ getConfig(): DbEncryptionConfig;
52
+ }
53
+ /**
54
+ * Set (or clear) the config without a Loadable factory — test harnesses and bootstrap
55
+ * contexts that run outside the source-repository graph.
56
+ */
57
+ export declare const setDbEncryptionConfig: (config?: DbEncryptionConfig) => void;
58
+ /** The registered config, or undefined when the deployment has none (a plaintext-only app). */
59
+ export declare const findDbEncryptionConfig: () => DbEncryptionConfig | undefined;
60
+ /** The registered config; throws a named error when encryption is used without one. */
61
+ export declare const getDbEncryptionConfig: () => DbEncryptionConfig;
62
+ //# sourceMappingURL=DbEncryptionConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DbEncryptionConfig.d.ts","sourceRoot":"","sources":["../../../src/encryption/DbEncryptionConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAoB,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;GAIG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;gBACvC,OAAO,EAAE,MAAM;CAO5B;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,iFAAiF;IACjF,iBAAiB,EAAE,iBAAiB,CAAC;IACrC;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAAC,MAAM,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC5F;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/E;;;;;OAKG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,mGAAmG;AACnG,MAAM,WAAW,yBAA0B,SAAQ,QAAQ;IACzD,SAAS,IAAI,kBAAkB,CAAC;CACjC;AAID;;;GAGG;AACH,eAAO,MAAM,qBAAqB,YAAa,kBAAkB,SAEhE,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,sBAAsB,QAAO,kBAAkB,GAAG,SAS9D,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,qBAAqB,QAAO,kBAWxC,CAAC"}
@@ -0,0 +1,67 @@
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.getDbEncryptionConfig = exports.findDbEncryptionConfig = exports.setDbEncryptionConfig = exports.EncryptedColumnConfigError = void 0;
19
+ var reflection_1 = require("@proteinjs/reflection");
20
+ /**
21
+ * A column-encryption configuration problem — a misdeclared column, a missing
22
+ * `DbEncryptionConfigFactory`, an unresolvable key owner. Always a dev-time/boot-time
23
+ * error class, never a data error.
24
+ */
25
+ var EncryptedColumnConfigError = /** @class */ (function (_super) {
26
+ __extends(EncryptedColumnConfigError, _super);
27
+ function EncryptedColumnConfigError(message) {
28
+ var _this = _super.call(this, message) || this;
29
+ _this.name = 'EncryptedColumnConfigError';
30
+ // ES5 down-leveled `extends Error` loses the subclass prototype — restore it so
31
+ // `instanceof` holds for catchers.
32
+ Object.setPrototypeOf(_this, EncryptedColumnConfigError.prototype);
33
+ return _this;
34
+ }
35
+ return EncryptedColumnConfigError;
36
+ }(Error));
37
+ exports.EncryptedColumnConfigError = EncryptedColumnConfigError;
38
+ var configOverride;
39
+ /**
40
+ * Set (or clear) the config without a Loadable factory — test harnesses and bootstrap
41
+ * contexts that run outside the source-repository graph.
42
+ */
43
+ var setDbEncryptionConfig = function (config) {
44
+ configOverride = config;
45
+ };
46
+ exports.setDbEncryptionConfig = setDbEncryptionConfig;
47
+ /** The registered config, or undefined when the deployment has none (a plaintext-only app). */
48
+ var findDbEncryptionConfig = function () {
49
+ if (configOverride) {
50
+ return configOverride;
51
+ }
52
+ var factory = reflection_1.SourceRepository.get().object('@proteinjs/db/DbEncryptionConfigFactory');
53
+ return factory === null || factory === void 0 ? void 0 : factory.getConfig();
54
+ };
55
+ exports.findDbEncryptionConfig = findDbEncryptionConfig;
56
+ /** The registered config; throws a named error when encryption is used without one. */
57
+ var getDbEncryptionConfig = function () {
58
+ var config = (0, exports.findDbEncryptionConfig)();
59
+ if (!config) {
60
+ throw new EncryptedColumnConfigError("A column declares 'encrypted' but no DbEncryptionConfig is registered. Implement " +
61
+ "@proteinjs/db/DbEncryptionConfigFactory (or call setDbEncryptionConfig) with a " +
62
+ "masterKeyProvider before using encrypted columns.");
63
+ }
64
+ return config;
65
+ };
66
+ exports.getDbEncryptionConfig = getDbEncryptionConfig;
67
+ //# sourceMappingURL=DbEncryptionConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DbEncryptionConfig.js","sourceRoot":"","sources":["../../../src/encryption/DbEncryptionConfig.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,oDAAmE;AAInE;;;;GAIG;AACH;IAAgD,8CAAK;IACnD,oCAAY,OAAe;QAA3B,YACE,kBAAM,OAAO,CAAC,SAKf;QAJC,KAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;QACzC,gFAAgF;QAChF,mCAAmC;QACnC,MAAM,CAAC,cAAc,CAAC,KAAI,EAAE,0BAA0B,CAAC,SAAS,CAAC,CAAC;;IACpE,CAAC;IACH,iCAAC;AAAD,CAAC,AARD,CAAgD,KAAK,GAQpD;AARY,gEAA0B;AAgDvC,IAAI,cAA8C,CAAC;AAEnD;;;GAGG;AACI,IAAM,qBAAqB,GAAG,UAAC,MAA2B;IAC/D,cAAc,GAAG,MAAM,CAAC;AAC1B,CAAC,CAAC;AAFW,QAAA,qBAAqB,yBAEhC;AAEF,+FAA+F;AACxF,IAAM,sBAAsB,GAAG;IACpC,IAAI,cAAc,EAAE;QAClB,OAAO,cAAc,CAAC;KACvB;IAED,IAAM,OAAO,GAAG,6BAAgB,CAAC,GAAG,EAAE,CAAC,MAAM,CAC3C,yCAAyC,CAC1C,CAAC;IACF,OAAO,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,SAAS,EAAE,CAAC;AAC9B,CAAC,CAAC;AATW,QAAA,sBAAsB,0BASjC;AAEF,uFAAuF;AAChF,IAAM,qBAAqB,GAAG;IACnC,IAAM,MAAM,GAAG,IAAA,8BAAsB,GAAE,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,IAAI,0BAA0B,CAClC,mFAAmF;YACjF,iFAAiF;YACjF,mDAAmD,CACtD,CAAC;KACH;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAXW,QAAA,qBAAqB,yBAWhC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A query asked an encrypted column for a shape outside the compatibility contract
3
+ * (`EncryptionQueryTranslator`). Thrown at query-build time, before any statement runs —
4
+ * the message names the limitation and the sanctioned paths, so the limitation cannot be
5
+ * hit silently.
6
+ */
7
+ export declare class EncryptedColumnQueryError extends Error {
8
+ constructor(message: string);
9
+ }
10
+ //# sourceMappingURL=EncryptedColumnQueryError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EncryptedColumnQueryError.d.ts","sourceRoot":"","sources":["../../../src/encryption/EncryptedColumnQueryError.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM;CAO5B"}