@proteinjs/user-server 1.13.0 → 1.15.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.
@@ -0,0 +1,571 @@
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
19
+ return new (P || (P = Promise))(function (resolve, reject) {
20
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
21
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
22
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
23
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
24
+ });
25
+ };
26
+ var __generator = (this && this.__generator) || function (thisArg, body) {
27
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
28
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
29
+ function verb(n) { return function (v) { return step([n, v]); }; }
30
+ function step(op) {
31
+ if (f) throw new TypeError("Generator is already executing.");
32
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
33
+ 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;
34
+ if (y = 0, t) op = [op[0] & 2, t.value];
35
+ switch (op[0]) {
36
+ case 0: case 1: t = op; break;
37
+ case 4: _.label++; return { value: op[1], done: false };
38
+ case 5: _.label++; y = op[1]; op = [0]; continue;
39
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
40
+ default:
41
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
42
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
43
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
44
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
45
+ if (t[2]) _.ops.pop();
46
+ _.trys.pop(); continue;
47
+ }
48
+ op = body.call(thisArg, _);
49
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
50
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
51
+ }
52
+ };
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ var db_1 = require("@proteinjs/db");
55
+ var test_1 = require("@proteinjs/db-driver-spanner/test");
56
+ var user_1 = require("@proteinjs/user");
57
+ var UserServerTestEnvironment_1 = require("./UserServerTestEnvironment");
58
+ var EncSharedNoteTable = /** @class */ (function (_super) {
59
+ __extends(EncSharedNoteTable, _super);
60
+ function EncSharedNoteTable() {
61
+ var _this = _super !== null && _super.apply(this, arguments) || this;
62
+ _this.name = 'user_test_enc_shared_note';
63
+ _this.auth = {
64
+ db: { all: 'authenticated' },
65
+ service: { all: 'authenticated' },
66
+ };
67
+ _this.columns = (0, user_1.withSharedRecordColumns)({
68
+ title: new db_1.StringColumn('title', { encrypted: { searchable: 'contains' } }),
69
+ label: new db_1.StringColumn('label', { encrypted: { searchable: 'equality' } }),
70
+ body: new db_1.StringColumn('body', { encrypted: {} }, 'MAX'),
71
+ kind: new db_1.StringColumn('kind', { encrypted: false }),
72
+ });
73
+ return _this;
74
+ }
75
+ return EncSharedNoteTable;
76
+ }(db_1.Table));
77
+ var testEnv = new UserServerTestEnvironment_1.UserServerTestEnvironment();
78
+ var noteTable = new EncSharedNoteTable();
79
+ var keyOwners = new user_1.SharedScopeKeyOwners();
80
+ var envelope = new db_1.EncryptionEnvelope();
81
+ var rawColumn = function (id, columnName) { return __awaiter(void 0, void 0, void 0, function () {
82
+ var rows;
83
+ var _a;
84
+ return __generator(this, function (_b) {
85
+ switch (_b.label) {
86
+ case 0: return [4 /*yield*/, testEnv.spannerDriver.runQuery(function () { return ({
87
+ sql: "SELECT `".concat(columnName, "` FROM `").concat(noteTable.name, "` WHERE `id` = '").concat(id, "'"),
88
+ }); })];
89
+ case 1:
90
+ rows = _b.sent();
91
+ return [2 /*return*/, (_a = rows[0]) === null || _a === void 0 ? void 0 : _a[columnName]];
92
+ }
93
+ });
94
+ }); };
95
+ var titleLike = function (pattern) {
96
+ return new db_1.QueryBuilder(noteTable.name).condition({ field: 'title', operator: 'LIKE', value: pattern });
97
+ };
98
+ var clearResolvedOwnerCache = function () {
99
+ var _a;
100
+ (_a = globalThis['__proteinjs_user_sharedScopeOwnerCache']) === null || _a === void 0 ? void 0 : _a.clear();
101
+ };
102
+ describe('Shared-scope encryption: owner-keyed scopes, share/revoke, support path', function () {
103
+ var dropTestTable = (0, test_1.getDropTestTable)(testEnv.spannerDriver);
104
+ var owner; // O — creates the document
105
+ var writer; // W — write-grant contributor
106
+ var support; // S — the §4.4 support principal (read grant via the help flow)
107
+ var stranger; // X — never granted
108
+ var coOwner; // C — conferred owner (owner-ceiling path)
109
+ var root;
110
+ var supportGrantId;
111
+ beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
112
+ var tableManager, db;
113
+ return __generator(this, function (_a) {
114
+ switch (_a.label) {
115
+ case 0: return [4 /*yield*/, testEnv.beforeAll()];
116
+ case 1:
117
+ _a.sent();
118
+ // Register the suite's table for name-based resolution (statement generation and the
119
+ // derived token-table subqueries resolve through `tableByName`), then create the
120
+ // physical schema: the framework's key table + the note table (its token table and
121
+ // companion columns ride the same load).
122
+ (0, db_1.getTables)().push(noteTable);
123
+ tableManager = testEnv.spannerDriver.getTableManager();
124
+ return [4 /*yield*/, tableManager.loadTable(new db_1.DataEncryptionKeyTable())];
125
+ case 2:
126
+ _a.sent();
127
+ return [4 /*yield*/, tableManager.loadTable(noteTable)];
128
+ case 3:
129
+ _a.sent();
130
+ (0, db_1.setDbEncryptionConfig)({
131
+ masterKeyProvider: new db_1.InMemoryMasterKeyProvider('shared-scope-encryption-test'),
132
+ resolveKeyOwner: function (args) { return keyOwners.resolveKeyOwner(args); },
133
+ getAccessibleKeyOwners: function (args) { return keyOwners.getAccessibleKeyOwners(args); },
134
+ });
135
+ db = (0, db_1.getDbAsSystem)();
136
+ return [4 /*yield*/, db.delete(user_1.tables.AccessGrant, {})];
137
+ case 4:
138
+ _a.sent();
139
+ return [4 /*yield*/, db.delete(user_1.tables.User, {})];
140
+ case 5:
141
+ _a.sent();
142
+ return [4 /*yield*/, db.delete(new db_1.DataEncryptionKeyTable(), {})];
143
+ case 6:
144
+ _a.sent();
145
+ clearResolvedOwnerCache();
146
+ return [4 /*yield*/, testEnv.createUser({ name: 'Enc Owner', email: 'enc-owner@test.local' })];
147
+ case 7:
148
+ owner = _a.sent();
149
+ return [4 /*yield*/, testEnv.createUser({ name: 'Enc Writer', email: 'enc-writer@test.local' })];
150
+ case 8:
151
+ writer = _a.sent();
152
+ return [4 /*yield*/, testEnv.createUser({ name: 'Enc Support', email: 'enc-support@test.local' })];
153
+ case 9:
154
+ support = _a.sent();
155
+ return [4 /*yield*/, testEnv.createUser({ name: 'Enc Stranger', email: 'enc-stranger@test.local' })];
156
+ case 10:
157
+ stranger = _a.sent();
158
+ return [4 /*yield*/, testEnv.createUser({ name: 'Enc CoOwner', email: 'enc-coowner@test.local' })];
159
+ case 11:
160
+ coOwner = _a.sent();
161
+ return [2 /*return*/];
162
+ }
163
+ });
164
+ }); }, 180000);
165
+ afterAll(function () { return __awaiter(void 0, void 0, void 0, function () {
166
+ return __generator(this, function (_a) {
167
+ switch (_a.label) {
168
+ case 0:
169
+ (0, db_1.setDbEncryptionConfig)(undefined);
170
+ clearResolvedOwnerCache();
171
+ return [4 /*yield*/, dropTestTable(new db_1.EncryptedColumns().tokenTableFor(noteTable))];
172
+ case 1:
173
+ _a.sent();
174
+ return [4 /*yield*/, dropTestTable(noteTable)];
175
+ case 2:
176
+ _a.sent();
177
+ return [4 /*yield*/, dropTestTable(new db_1.DataEncryptionKeyTable())];
178
+ case 3:
179
+ _a.sent();
180
+ return [4 /*yield*/, testEnv.afterAll()];
181
+ case 4:
182
+ _a.sent();
183
+ return [2 /*return*/];
184
+ }
185
+ });
186
+ }); }, 120000);
187
+ test('root birth: the creator keys the scope — ciphertext at rest names the owner', function () { return __awaiter(void 0, void 0, void 0, function () {
188
+ var _i, _a, columnName, stored, _b, grants, keyRows, fetched;
189
+ return __generator(this, function (_c) {
190
+ switch (_c.label) {
191
+ case 0:
192
+ testEnv.actAs(owner);
193
+ return [4 /*yield*/, (0, user_1.getSharedDb)().insert(noteTable, {
194
+ title: 'Therapy notes shared scope',
195
+ label: 'case-407',
196
+ body: 'The sensitive body text',
197
+ kind: 'note',
198
+ })];
199
+ case 1:
200
+ root = _c.sent();
201
+ _i = 0, _a = ['title', 'label', 'body'];
202
+ _c.label = 2;
203
+ case 2:
204
+ if (!(_i < _a.length)) return [3 /*break*/, 5];
205
+ columnName = _a[_i];
206
+ return [4 /*yield*/, rawColumn(root.id, columnName)];
207
+ case 3:
208
+ stored = _c.sent();
209
+ expect(envelope.isEnvelope(stored)).toBe(true);
210
+ expect(String(stored)).not.toContain('Therapy');
211
+ expect(String(stored)).not.toContain('sensitive');
212
+ expect(envelope.parse(stored).owner).toBe(owner.id);
213
+ _c.label = 4;
214
+ case 4:
215
+ _i++;
216
+ return [3 /*break*/, 2];
217
+ case 5:
218
+ _b = expect;
219
+ return [4 /*yield*/, rawColumn(root.id, 'kind')];
220
+ case 6:
221
+ _b.apply(void 0, [_c.sent()]).toBe('note');
222
+ return [4 /*yield*/, (0, db_1.getDbAsSystem)().query(user_1.tables.AccessGrant, new db_1.QueryBuilder(user_1.tables.AccessGrant.name)
223
+ .condition({ field: 'resource', operator: '=', value: root.id })
224
+ .condition({ field: 'accessLevel', operator: '=', value: 'owner' }))];
225
+ case 7:
226
+ grants = _c.sent();
227
+ expect(grants.map(function (grant) { var _a; return (_a = grant.principal) === null || _a === void 0 ? void 0 : _a._id; })).toEqual([owner.id]);
228
+ return [4 /*yield*/, (0, db_1.getDbAsSystem)().query(new db_1.DataEncryptionKeyTable(), {})];
229
+ case 8:
230
+ keyRows = _c.sent();
231
+ expect(keyRows.map(function (row) { return row.owner; })).toEqual([owner.id]);
232
+ return [4 /*yield*/, (0, user_1.getSharedDb)().get(noteTable, { id: root.id })];
233
+ case 9:
234
+ fetched = _c.sent();
235
+ expect(fetched.title).toBe('Therapy notes shared scope');
236
+ expect(fetched.body).toBe('The sensitive body text');
237
+ return [2 /*return*/];
238
+ }
239
+ });
240
+ }); });
241
+ test('share with support: a read grant extends decrypt + search to the recipient (§4.4)', function () { return __awaiter(void 0, void 0, void 0, function () {
242
+ var supportGrant, fetched, found, byLabel, supportKeys;
243
+ return __generator(this, function (_a) {
244
+ switch (_a.label) {
245
+ case 0:
246
+ // O performs the share — an ordinary direct grant, exactly what the help-flow
247
+ // affordance will mint. Caller-context: the grant table's own gate admits O (owner).
248
+ testEnv.actAs(owner);
249
+ return [4 /*yield*/, (0, db_1.getDb)().insert(user_1.tables.AccessGrant, {
250
+ principal: new db_1.Reference(user_1.tables.User.name, support.id),
251
+ resource: new db_1.Reference(noteTable.name, root.id),
252
+ resourceTable: noteTable.name,
253
+ accessLevel: 'read',
254
+ })];
255
+ case 1:
256
+ supportGrant = _a.sent();
257
+ supportGrantId = supportGrant.id;
258
+ testEnv.actAs(support);
259
+ return [4 /*yield*/, (0, user_1.getSharedDb)().get(noteTable, { id: root.id })];
260
+ case 2:
261
+ fetched = _a.sent();
262
+ expect(fetched.title).toBe('Therapy notes shared scope');
263
+ expect(fetched.body).toBe('The sensitive body text');
264
+ return [4 /*yield*/, (0, user_1.getSharedDb)().query(noteTable, titleLike('%Therapy notes%'))];
265
+ case 3:
266
+ found = _a.sent();
267
+ expect(found.map(function (row) { return row.id; })).toEqual([root.id]);
268
+ return [4 /*yield*/, (0, user_1.getSharedDb)().query(noteTable, { label: 'case-407' })];
269
+ case 4:
270
+ byLabel = _a.sent();
271
+ expect(byLabel.map(function (row) { return row.id; })).toEqual([root.id]);
272
+ return [4 /*yield*/, (0, db_1.getDbAsSystem)().query(new db_1.DataEncryptionKeyTable(), {
273
+ owner: support.id,
274
+ })];
275
+ case 5:
276
+ supportKeys = _a.sent();
277
+ expect(supportKeys.length).toBe(0);
278
+ return [2 /*return*/];
279
+ }
280
+ });
281
+ }); });
282
+ test('a stranger sees nothing: no rows, and search covers only their own (empty) key set', function () { return __awaiter(void 0, void 0, void 0, function () {
283
+ var _a, _b, _c;
284
+ return __generator(this, function (_d) {
285
+ switch (_d.label) {
286
+ case 0:
287
+ testEnv.actAs(stranger);
288
+ _a = expect;
289
+ return [4 /*yield*/, (0, user_1.getSharedDb)().get(noteTable, { id: root.id })];
290
+ case 1:
291
+ _a.apply(void 0, [_d.sent()]).toBeUndefined();
292
+ _b = expect;
293
+ return [4 /*yield*/, (0, user_1.getSharedDb)().query(noteTable, titleLike('%Therapy%'))];
294
+ case 2:
295
+ _b.apply(void 0, [_d.sent()]).toEqual([]);
296
+ _c = expect;
297
+ return [4 /*yield*/, keyOwners.getAccessibleKeyOwners({ runAsSystem: false })];
298
+ case 3:
299
+ _c.apply(void 0, [_d.sent()]).toEqual([stranger.id]);
300
+ return [2 /*return*/];
301
+ }
302
+ });
303
+ }); });
304
+ test("a contributor's write into the shared scope keys under the DOCUMENT owner, not the writer", function () { return __awaiter(void 0, void 0, void 0, function () {
305
+ var child, stored, own, _a, _b, _c, lineRows, noteRows;
306
+ return __generator(this, function (_d) {
307
+ switch (_d.label) {
308
+ case 0:
309
+ testEnv.actAs(owner);
310
+ return [4 /*yield*/, (0, db_1.getDb)().insert(user_1.tables.AccessGrant, {
311
+ principal: new db_1.Reference(user_1.tables.User.name, writer.id),
312
+ resource: new db_1.Reference(noteTable.name, root.id),
313
+ resourceTable: noteTable.name,
314
+ accessLevel: 'write',
315
+ })];
316
+ case 1:
317
+ _d.sent();
318
+ // Fresh resolution (no cache): the write must derive the owner from the GRANT record.
319
+ clearResolvedOwnerCache();
320
+ testEnv.actAs(writer);
321
+ return [4 /*yield*/, (0, user_1.getSharedDbWithOverride)().insert(noteTable, {
322
+ title: 'Contributor note addendum line',
323
+ label: 'addendum',
324
+ body: null,
325
+ kind: 'note',
326
+ permissionSource: new db_1.Reference(noteTable.name, root.id),
327
+ })];
328
+ case 2:
329
+ child = _d.sent();
330
+ return [4 /*yield*/, rawColumn(child.id, 'title')];
331
+ case 3:
332
+ stored = _d.sent();
333
+ expect(envelope.isEnvelope(stored)).toBe(true);
334
+ expect(envelope.parse(stored).owner).toBe(owner.id);
335
+ expect(envelope.parse(stored).owner).not.toBe(writer.id);
336
+ return [4 /*yield*/, (0, user_1.getSharedDb)().insert(noteTable, {
337
+ title: 'Writer private note planning',
338
+ label: 'own',
339
+ body: null,
340
+ kind: 'note',
341
+ })];
342
+ case 4:
343
+ own = _d.sent();
344
+ _a = expect;
345
+ _c = (_b = envelope).parse;
346
+ return [4 /*yield*/, rawColumn(own.id, 'title')];
347
+ case 5:
348
+ _a.apply(void 0, [_c.apply(_b, [_d.sent()]).owner]).toBe(writer.id);
349
+ return [4 /*yield*/, (0, user_1.getSharedDb)().query(noteTable, titleLike('%addendum line%'))];
350
+ case 6:
351
+ lineRows = _d.sent();
352
+ expect(lineRows.map(function (row) { return row.title; })).toEqual(['Contributor note addendum line']);
353
+ return [4 /*yield*/, (0, user_1.getSharedDb)().query(noteTable, titleLike('%note%'))];
354
+ case 7:
355
+ noteRows = _d.sent();
356
+ expect(noteRows.map(function (row) { return row.title; }).sort()).toEqual([
357
+ 'Contributor note addendum line',
358
+ 'Therapy notes shared scope',
359
+ 'Writer private note planning',
360
+ ]);
361
+ return [2 /*return*/];
362
+ }
363
+ });
364
+ }); });
365
+ test('owner key rotation honors shares: old and new envelopes both decrypt and search for the recipient', function () { return __awaiter(void 0, void 0, void 0, function () {
366
+ var newVersion, rotated, _a, _b, _c, _d, _e, _f, fetchedOld, fetchedNew, lower, both;
367
+ return __generator(this, function (_g) {
368
+ switch (_g.label) {
369
+ case 0: return [4 /*yield*/, new db_1.DataKeyStore().rotateKey(owner.id)];
370
+ case 1:
371
+ newVersion = _g.sent();
372
+ expect(newVersion).toBe(2);
373
+ testEnv.actAs(owner);
374
+ return [4 /*yield*/, (0, user_1.getSharedDbWithOverride)().insert(noteTable, {
375
+ title: 'Post-rotation Therapy addendum',
376
+ label: 'rotated',
377
+ body: null,
378
+ kind: 'note',
379
+ permissionSource: new db_1.Reference(noteTable.name, root.id),
380
+ })];
381
+ case 2:
382
+ rotated = _g.sent();
383
+ _a = expect;
384
+ _c = (_b = envelope).parse;
385
+ return [4 /*yield*/, rawColumn(rotated.id, 'title')];
386
+ case 3:
387
+ _a.apply(void 0, [_c.apply(_b, [_g.sent()]).version]).toBe(2);
388
+ _d = expect;
389
+ _f = (_e = envelope).parse;
390
+ return [4 /*yield*/, rawColumn(root.id, 'title')];
391
+ case 4:
392
+ _d.apply(void 0, [_f.apply(_e, [_g.sent()]).version]).toBe(1);
393
+ testEnv.actAs(support);
394
+ return [4 /*yield*/, (0, user_1.getSharedDb)().get(noteTable, { id: root.id })];
395
+ case 5:
396
+ fetchedOld = _g.sent();
397
+ return [4 /*yield*/, (0, user_1.getSharedDb)().get(noteTable, { id: rotated.id })];
398
+ case 6:
399
+ fetchedNew = _g.sent();
400
+ expect(fetchedOld.title).toBe('Therapy notes shared scope');
401
+ expect(fetchedNew.title).toBe('Post-rotation Therapy addendum');
402
+ return [4 /*yield*/, (0, user_1.getSharedDb)().query(noteTable, titleLike('%therapy%'))];
403
+ case 7:
404
+ lower = _g.sent();
405
+ expect(lower.length).toBe(0); // LIKE stays case-exact over encrypted values
406
+ return [4 /*yield*/, (0, user_1.getSharedDb)().query(noteTable, titleLike('%Therapy%'))];
407
+ case 8:
408
+ both = _g.sent();
409
+ expect(both.map(function (row) { return row.id; }).sort()).toEqual([root.id, rotated.id].sort());
410
+ return [2 /*return*/];
411
+ }
412
+ });
413
+ }); });
414
+ test('conferred co-ownership: the scope keeps keying by its ORIGINAL owner, and the co-owner searches it', function () { return __awaiter(void 0, void 0, void 0, function () {
415
+ var coWrite, _a, _b, _c, accessible, found;
416
+ return __generator(this, function (_d) {
417
+ switch (_d.label) {
418
+ case 0:
419
+ testEnv.actAs(owner);
420
+ return [4 /*yield*/, (0, db_1.getDb)().insert(user_1.tables.AccessGrant, {
421
+ principal: new db_1.Reference(user_1.tables.User.name, coOwner.id),
422
+ resource: new db_1.Reference(noteTable.name, root.id),
423
+ resourceTable: noteTable.name,
424
+ accessLevel: 'owner', // legal: O holds owner (the owner-ceiling path)
425
+ })];
426
+ case 1:
427
+ _d.sent();
428
+ // Fresh resolution (no cache): the EARLIEST owner grant — O's — still keys new writes.
429
+ clearResolvedOwnerCache();
430
+ testEnv.actAs(coOwner);
431
+ return [4 /*yield*/, (0, user_1.getSharedDbWithOverride)().insert(noteTable, {
432
+ title: 'Co-owner amendment entry',
433
+ label: 'co-owner',
434
+ body: null,
435
+ kind: 'note',
436
+ permissionSource: new db_1.Reference(noteTable.name, root.id),
437
+ })];
438
+ case 2:
439
+ coWrite = _d.sent();
440
+ _a = expect;
441
+ _c = (_b = envelope).parse;
442
+ return [4 /*yield*/, rawColumn(coWrite.id, 'title')];
443
+ case 3:
444
+ _a.apply(void 0, [_c.apply(_b, [_d.sent()]).owner]).toBe(owner.id);
445
+ return [4 /*yield*/, keyOwners.getAccessibleKeyOwners({ runAsSystem: false })];
446
+ case 4:
447
+ accessible = _d.sent();
448
+ expect(accessible.sort()).toEqual([coOwner.id, owner.id].sort());
449
+ return [4 /*yield*/, (0, user_1.getSharedDb)().query(noteTable, titleLike('%amendment%'))];
450
+ case 5:
451
+ found = _d.sent();
452
+ expect(found.map(function (row) { return row.id; })).toEqual([coWrite.id]);
453
+ return [2 /*return*/];
454
+ }
455
+ });
456
+ }); });
457
+ test('revocation ends access and fan-out immediately — with NO re-encryption', function () { return __awaiter(void 0, void 0, void 0, function () {
458
+ var cipherBefore, revoked, _a, _b, _c, _d;
459
+ return __generator(this, function (_e) {
460
+ switch (_e.label) {
461
+ case 0: return [4 /*yield*/, rawColumn(root.id, 'title')];
462
+ case 1:
463
+ cipherBefore = _e.sent();
464
+ testEnv.actAs(owner);
465
+ return [4 /*yield*/, (0, db_1.getDb)().delete(user_1.tables.AccessGrant, { id: supportGrantId })];
466
+ case 2:
467
+ revoked = _e.sent();
468
+ expect(revoked).toBe(1);
469
+ testEnv.actAs(support);
470
+ _a = expect;
471
+ return [4 /*yield*/, (0, user_1.getSharedDb)().get(noteTable, { id: root.id })];
472
+ case 3:
473
+ _a.apply(void 0, [_e.sent()]).toBeUndefined();
474
+ _b = expect;
475
+ return [4 /*yield*/, (0, user_1.getSharedDb)().query(noteTable, titleLike('%Therapy%'))];
476
+ case 4:
477
+ _b.apply(void 0, [_e.sent()]).toEqual([]);
478
+ _c = expect;
479
+ return [4 /*yield*/, keyOwners.getAccessibleKeyOwners({ runAsSystem: false })];
480
+ case 5:
481
+ _c.apply(void 0, [_e.sent()]).toEqual([support.id]);
482
+ // Keys are not access control: the row's ciphertext is byte-identical — revocation is
483
+ // the permission layer's act, never a re-encryption.
484
+ _d = expect;
485
+ return [4 /*yield*/, rawColumn(root.id, 'title')];
486
+ case 6:
487
+ // Keys are not access control: the row's ciphertext is byte-identical — revocation is
488
+ // the permission layer's act, never a re-encryption.
489
+ _d.apply(void 0, [_e.sent()]).toBe(cipherBefore);
490
+ return [2 /*return*/];
491
+ }
492
+ });
493
+ }); });
494
+ test('system reads decrypt without caller context — the compliance-decrypt seam composes', function () { return __awaiter(void 0, void 0, void 0, function () {
495
+ var fetched;
496
+ return __generator(this, function (_a) {
497
+ switch (_a.label) {
498
+ case 0: return [4 /*yield*/, (0, db_1.getDbAsSystem)().get(noteTable, { id: root.id })];
499
+ case 1:
500
+ fetched = _a.sent();
501
+ expect(fetched.title).toBe('Therapy notes shared scope');
502
+ expect(fetched.body).toBe('The sensitive body text');
503
+ return [2 /*return*/];
504
+ }
505
+ });
506
+ }); });
507
+ test('system searches cover EVERY key owner — an unscoped query never silently misses a scope', function () { return __awaiter(void 0, void 0, void 0, function () {
508
+ var rows, rowOwners, _i, rows_1, row, _a, _b, _c, _d;
509
+ return __generator(this, function (_e) {
510
+ switch (_e.label) {
511
+ case 0: return [4 /*yield*/, (0, db_1.getDbAsSystem)().query(noteTable, titleLike('%note%'))];
512
+ case 1:
513
+ rows = _e.sent();
514
+ rowOwners = new Set();
515
+ _i = 0, rows_1 = rows;
516
+ _e.label = 2;
517
+ case 2:
518
+ if (!(_i < rows_1.length)) return [3 /*break*/, 5];
519
+ row = rows_1[_i];
520
+ _b = (_a = rowOwners).add;
521
+ _d = (_c = envelope).parse;
522
+ return [4 /*yield*/, rawColumn(row.id, 'title')];
523
+ case 3:
524
+ _b.apply(_a, [_d.apply(_c, [_e.sent()]).owner]);
525
+ _e.label = 4;
526
+ case 4:
527
+ _i++;
528
+ return [3 /*break*/, 2];
529
+ case 5:
530
+ // Spans O's scope AND W's private document — both key owners covered in one query.
531
+ expect(rowOwners.has(owner.id)).toBe(true);
532
+ expect(rowOwners.has(writer.id)).toBe(true);
533
+ return [2 /*return*/];
534
+ }
535
+ });
536
+ }); });
537
+ test('the resolver contract: non-shared tables fall through; caller-less searches refuse loudly', function () { return __awaiter(void 0, void 0, void 0, function () {
538
+ var _a;
539
+ return __generator(this, function (_b) {
540
+ switch (_b.label) {
541
+ case 0:
542
+ _a = expect;
543
+ return [4 /*yield*/, keyOwners.resolveKeyOwner({ table: user_1.tables.User, record: owner })];
544
+ case 1:
545
+ _a.apply(void 0, [_b.sent()]).toBeUndefined();
546
+ testEnv.actAs({});
547
+ return [4 /*yield*/, expect(keyOwners.getAccessibleKeyOwners({ runAsSystem: false })).rejects.toThrow(/without a caller identity/)];
548
+ case 2:
549
+ _b.sent();
550
+ testEnv.actAs(owner);
551
+ return [2 /*return*/];
552
+ }
553
+ });
554
+ }); });
555
+ test('crypto-shred: deleting the owner keys makes every envelope in the scope permanently unreadable', function () { return __awaiter(void 0, void 0, void 0, function () {
556
+ var deleted;
557
+ return __generator(this, function (_a) {
558
+ switch (_a.label) {
559
+ case 0: return [4 /*yield*/, new db_1.DataKeyStore().shredOwnerKeys(owner.id)];
560
+ case 1:
561
+ deleted = _a.sent();
562
+ expect(deleted).toBeGreaterThanOrEqual(2); // v1 + v2
563
+ return [4 /*yield*/, expect((0, db_1.getDbAsSystem)().get(noteTable, { id: root.id })).rejects.toThrow(/No data key exists for owner/)];
564
+ case 2:
565
+ _a.sent();
566
+ return [2 /*return*/];
567
+ }
568
+ });
569
+ }); });
570
+ });
571
+ //# sourceMappingURL=SharedScopeEncryption.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SharedScopeEncryption.integration.test.js","sourceRoot":"","sources":["../../test/SharedScopeEncryption.integration.test.ts"],"names":[],"mappings":"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"}