@substrat-run/contract-tests 0.142.0 → 0.144.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 (73) hide show
  1. package/dist/attachment-refusal-suite.d.ts +3 -0
  2. package/dist/attachment-refusal-suite.d.ts.map +1 -0
  3. package/dist/attachment-refusal-suite.js +128 -0
  4. package/dist/attachment-refusal-suite.js.map +1 -0
  5. package/dist/bind-module.d.ts +199 -0
  6. package/dist/bind-module.d.ts.map +1 -0
  7. package/dist/bind-module.js +104 -0
  8. package/dist/bind-module.js.map +1 -0
  9. package/dist/binding-invite-suite.d.ts +12 -0
  10. package/dist/binding-invite-suite.d.ts.map +1 -0
  11. package/dist/binding-invite-suite.js +507 -0
  12. package/dist/binding-invite-suite.js.map +1 -0
  13. package/dist/caused-by-module.d.ts.map +1 -1
  14. package/dist/caused-by-module.js +3 -2
  15. package/dist/caused-by-module.js.map +1 -1
  16. package/dist/derived-module.d.ts +690 -0
  17. package/dist/derived-module.d.ts.map +1 -0
  18. package/dist/derived-module.js +320 -0
  19. package/dist/derived-module.js.map +1 -0
  20. package/dist/derived-suite.d.ts +3 -0
  21. package/dist/derived-suite.d.ts.map +1 -0
  22. package/dist/derived-suite.js +481 -0
  23. package/dist/derived-suite.js.map +1 -0
  24. package/dist/entity-state-module.d.ts.map +1 -1
  25. package/dist/entity-state-module.js +12 -6
  26. package/dist/entity-state-module.js.map +1 -1
  27. package/dist/entity-trash-module.d.ts.map +1 -1
  28. package/dist/entity-trash-module.js +4 -4
  29. package/dist/entity-trash-module.js.map +1 -1
  30. package/dist/entity-trash-suite.d.ts.map +1 -1
  31. package/dist/entity-trash-suite.js +17 -8
  32. package/dist/entity-trash-suite.js.map +1 -1
  33. package/dist/erasure-module.d.ts.map +1 -1
  34. package/dist/erasure-module.js +3 -2
  35. package/dist/erasure-module.js.map +1 -1
  36. package/dist/index.d.ts +8 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +8 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/input-parse-suite.d.ts.map +1 -1
  41. package/dist/input-parse-suite.js +33 -2
  42. package/dist/input-parse-suite.js.map +1 -1
  43. package/dist/membership-module.d.ts.map +1 -1
  44. package/dist/membership-module.js +3 -2
  45. package/dist/membership-module.js.map +1 -1
  46. package/dist/migration-comments.d.ts.map +1 -1
  47. package/dist/migration-comments.js +3 -2
  48. package/dist/migration-comments.js.map +1 -1
  49. package/dist/modules.d.ts.map +1 -1
  50. package/dist/modules.js +78 -68
  51. package/dist/modules.js.map +1 -1
  52. package/dist/permission-suite.d.ts.map +1 -1
  53. package/dist/permission-suite.js +28 -0
  54. package/dist/permission-suite.js.map +1 -1
  55. package/dist/scope-host-suite.d.ts.map +1 -1
  56. package/dist/scope-host-suite.js +151 -31
  57. package/dist/scope-host-suite.js.map +1 -1
  58. package/dist/shape-backfill-ties.d.ts +29 -0
  59. package/dist/shape-backfill-ties.d.ts.map +1 -0
  60. package/dist/shape-backfill-ties.js +113 -0
  61. package/dist/shape-backfill-ties.js.map +1 -0
  62. package/dist/shape-reconcile-plan.d.ts +37 -0
  63. package/dist/shape-reconcile-plan.d.ts.map +1 -0
  64. package/dist/shape-reconcile-plan.js +143 -0
  65. package/dist/shape-reconcile-plan.js.map +1 -0
  66. package/dist/test-operations.d.ts +25 -0
  67. package/dist/test-operations.d.ts.map +1 -0
  68. package/dist/test-operations.js +22 -0
  69. package/dist/test-operations.js.map +1 -0
  70. package/dist/vertical-events-suite.d.ts.map +1 -1
  71. package/dist/vertical-events-suite.js +72 -7
  72. package/dist/vertical-events-suite.js.map +1 -1
  73. package/package.json +3 -3
@@ -0,0 +1,481 @@
1
+ /**
2
+ * Contract suite for the handlers the platform derives from a declaration (#1773).
3
+ *
4
+ * What it pins: **a derived handler owes what a hand-written one owes**, on each adapter's SQL.
5
+ * The declared check comes first, so a caller without the key learns `permission_denied` and nothing about
6
+ * whether the row exists. A missing row is `not_found`. A PATCH writes only the fields sent, and
7
+ * `null` clears. The host's 412 holds in front of it. Every write emits one event whose payload
8
+ * is the declared fields of the row as written. A page is scoped to its parent and walks whole,
9
+ * and a parent that does not exist is `not_found` (#2157). A create mints the id, fills the parent
10
+ * link and links the row to it, stamps the time and the caller, and answers the row that already
11
+ * holds its natural key without writing (#2157).
12
+ *
13
+ * The DEFAULT tuple checker, so a denial is a real one: `dave` holds no key at all, and every
14
+ * refusal has its positive twin from `alice`, who holds every key.
15
+ *
16
+ * The moves and the bin (#119) owe what todo's hand-written ones did: the entity's declared key,
17
+ * per move, checked on the row; `conflict` for a wrong move; the active view by default; the
18
+ * bin walked row by row under the trash key, so a key narrowed to one binned row shows that row.
19
+ */
20
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
21
+ import { defineEntities, defineOperations, entityStateOutput, errorCodeOf, etagOf, permissionKey, platformActorId, principalId, scopeId, tenantId, } from '@substrat-run/contracts';
22
+ import { ulid } from '@substrat-run/kernel';
23
+ import { z } from 'zod';
24
+ import { derivedMod } from './derived-module.js';
25
+ const KEYS = ['dnote:read', 'dnote:write', 'dshelf:archive', 'dshelf:trash'].map((k) => permissionKey.parse(k));
26
+ export function derivedHandlersContractSuite(adapterName, makeFixture) {
27
+ describe(`derived handlers (#1773): ${adapterName}`, () => {
28
+ let fixture;
29
+ let host;
30
+ const t = tenantId.parse(ulid());
31
+ const s = scopeId.parse(ulid());
32
+ const staff = platformActorId.parse(ulid());
33
+ const alice = principalId.parse(ulid());
34
+ const dave = principalId.parse(ulid());
35
+ const carl = principalId.parse(ulid());
36
+ let as;
37
+ let asDave;
38
+ let asCarl;
39
+ /** Every version the host reported, newest last — what an HTTP mount would set as `ETag`. */
40
+ let tags = [];
41
+ const sink = { onEntityVersion: (version) => tags.push(version) };
42
+ const codeOf = (call) => call.then(() => 'answered', (e) => errorCodeOf(e));
43
+ const messageOf = (call) => call.then(() => 'answered', (e) => e.message);
44
+ const addNote = async (folderId, title, rank, body = 'b') => {
45
+ const id = ulid();
46
+ await as.invoke('derived/add-note', { id, folderId, title, body, rank });
47
+ return { id, dfolder_id: folderId, title, body, rank };
48
+ };
49
+ const history = async (noteId) => (await as.invoke('derived/history', { noteId })).entries;
50
+ const get = (who, noteId) => who.invoke('derived/get-note', { noteId });
51
+ beforeAll(async () => {
52
+ fixture = await makeFixture();
53
+ host = fixture.host;
54
+ host.registerModule(derivedMod);
55
+ await host.admin.createTenant(staff, { id: t, slug: 'derived-tenant', name: 'Derived Tenant' });
56
+ await host.admin.grantEntitlement(staff, t, 'derived');
57
+ await host.admin.defineRole(staff, t, { key: 'derived-admin', permissions: KEYS, source: 'vertical' });
58
+ await host.admin.assignRole(staff, { principalId: alice, roleKey: 'derived-admin', node: { tenantId: t, scopeId: null } });
59
+ await host.admin.assignRole(staff, { principalId: carl, roleKey: 'derived-admin', node: { tenantId: t, scopeId: null } });
60
+ await host.provisionScope(staff, { tenantId: t, scopeId: s, vertical: 'derived-vertical' });
61
+ await host.admin.activateScope(staff, t, s);
62
+ as = await host.getScope(alice, t, s);
63
+ asDave = await host.getScope(dave, t, s);
64
+ asCarl = await host.getScope(carl, t, s);
65
+ await as.invoke('derived/add-folder', { id: 'fa', name: 'A' });
66
+ await as.invoke('derived/add-folder', { id: 'fb', name: 'B' });
67
+ await as.invoke('derived/add-folder', { id: 'fc', name: 'C, empty' });
68
+ });
69
+ afterAll(async () => {
70
+ await fixture.cleanup();
71
+ });
72
+ describe('get', () => {
73
+ it('answers the row, every declared column of it', async () => {
74
+ const n = await addNote('fa', 'one', 1, null);
75
+ expect(await get(as, n.id)).toEqual(n);
76
+ });
77
+ it('answers not_found for a missing row, in the words a hand-written read uses', async () => {
78
+ expect(await codeOf(get(as, 'missing'))).toBe('not_found');
79
+ expect(await messageOf(get(as, 'missing'))).toContain('dnote not found: missing');
80
+ });
81
+ it('checks first: a caller without the key is denied, whether or not the row exists', async () => {
82
+ const n = await addNote('fa', 'two', 2);
83
+ expect(await codeOf(get(asDave, n.id))).toBe('permission_denied');
84
+ expect(await codeOf(get(asDave, 'missing'))).toBe('permission_denied');
85
+ });
86
+ });
87
+ describe('update', () => {
88
+ const update = (who, input, ifMatch) => who.invoke('derived/update-note', input, { ...sink, ...(ifMatch === undefined ? {} : { ifMatch }) });
89
+ it('writes only the fields sent, and answers with the row as written', async () => {
90
+ const n = await addNote('fa', 'before', 3, 'kept');
91
+ const after = await update(as, { noteId: n.id, title: 'after' });
92
+ expect(after).toEqual({ ...n, title: 'after' });
93
+ expect(await get(as, n.id)).toEqual({ ...n, title: 'after' });
94
+ });
95
+ it('clears a nullable column on an explicit null, and leaves the rest alone', async () => {
96
+ const n = await addNote('fa', 'clear', 4, 'goes');
97
+ expect(await update(as, { noteId: n.id, body: null, rank: 40 })).toEqual({ ...n, body: null, rank: 40 });
98
+ });
99
+ it('emits one event, its payload the declared fields of the row as written', async () => {
100
+ const n = await addNote('fa', 'evt', 5);
101
+ await update(as, { noteId: n.id, title: 'evt2' });
102
+ const events = (await history(n.id)).filter((e) => e.type === 'dnote.updated');
103
+ expect(events).toHaveLength(1);
104
+ expect(events[0]?.payload).toEqual({ id: n.id, title: 'evt2', body: 'b', rank: 5 });
105
+ });
106
+ it('writes nothing and emits nothing when no field is sent', async () => {
107
+ const n = await addNote('fa', 'idle', 6);
108
+ const before = (await history(n.id)).length;
109
+ expect(await update(as, { noteId: n.id })).toEqual(n);
110
+ expect(await history(n.id)).toHaveLength(before);
111
+ });
112
+ it('is refused with precondition_failed on a stale tag, and leaves the row as it was', async () => {
113
+ const n = await addNote('fa', 'race', 7);
114
+ tags = [];
115
+ await update(as, { noteId: n.id, title: 'first' });
116
+ const stale = tags.at(-1);
117
+ expect(typeof stale).toBe('string');
118
+ await update(as, { noteId: n.id, title: 'second' }, etagOf(stale));
119
+ expect(await codeOf(update(as, { noteId: n.id, title: 'lost' }, etagOf(stale)))).toBe('precondition_failed');
120
+ expect((await get(as, n.id)).title).toBe('second');
121
+ });
122
+ it('answers not_found for a missing row, and denied first to a caller without the key', async () => {
123
+ expect(await codeOf(update(as, { noteId: 'missing', title: 'x' }))).toBe('not_found');
124
+ const n = await addNote('fa', 'guarded', 8);
125
+ expect(await codeOf(update(asDave, { noteId: n.id, title: 'x' }))).toBe('permission_denied');
126
+ expect(await codeOf(update(asDave, { noteId: 'missing', title: 'x' }))).toBe('permission_denied');
127
+ expect((await get(as, n.id)).title).toBe('guarded');
128
+ });
129
+ });
130
+ describe('delete', () => {
131
+ const del = (who, noteId) => who.invoke('derived/delete-note', { noteId });
132
+ it('removes the row, answers { id, deleted }, and emits about it', async () => {
133
+ const n = await addNote('fa', 'bye', 9);
134
+ expect(await del(as, n.id)).toEqual({ id: n.id, deleted: true });
135
+ expect(await codeOf(get(as, n.id))).toBe('not_found');
136
+ const events = (await history(n.id)).filter((e) => e.type === 'dnote.deleted');
137
+ expect(events).toHaveLength(1);
138
+ expect(events[0]?.payload).toEqual({ id: n.id });
139
+ });
140
+ it('answers not_found for a missing row, and denied first to a caller without the key', async () => {
141
+ expect(await codeOf(del(as, 'missing'))).toBe('not_found');
142
+ const n = await addNote('fa', 'stays', 10);
143
+ expect(await codeOf(del(asDave, n.id))).toBe('permission_denied');
144
+ expect(await codeOf(del(asDave, 'missing'))).toBe('permission_denied');
145
+ expect(await get(as, n.id)).toEqual(n);
146
+ });
147
+ });
148
+ describe('list', () => {
149
+ let inB;
150
+ beforeAll(async () => {
151
+ // Folder B alone, ranks out of insertion order, two titles shared — so the walk's order,
152
+ // its parent scope and its filter are each visible.
153
+ inB = [];
154
+ for (const [title, rank] of [['x', 30], ['y', 10], ['x', 20], ['z', 50], ['y', 40]]) {
155
+ inB.push(await addNote('fb', title, rank));
156
+ }
157
+ });
158
+ const walk = async (input, limit) => {
159
+ const seen = [];
160
+ let cursor;
161
+ for (let guard = 0; guard < 20; guard++) {
162
+ const page = await as.invoke('derived/list-notes', { ...input, limit, cursor });
163
+ seen.push(...page.entries);
164
+ if (page.nextCursor === null)
165
+ return seen;
166
+ cursor = page.nextCursor;
167
+ }
168
+ throw new Error('walk did not terminate — the cursor is not advancing');
169
+ };
170
+ const byRank = (rows) => [...rows].sort((a, b) => a.rank - b.rank);
171
+ it("walks the parent's rows whole, in the declared order, across pages", async () => {
172
+ expect(await walk({ dfolderId: 'fb' }, 2)).toEqual(byRank(inB));
173
+ });
174
+ it('counts the scoped set when the declaration asks for a total', async () => {
175
+ const page = await as.invoke('derived/list-notes', { dfolderId: 'fb', limit: 2 });
176
+ expect(page.total).toBe(inB.length);
177
+ });
178
+ it('applies a declared filter beside the parent, and none when it is absent', async () => {
179
+ expect(await walk({ dfolderId: 'fb', title: 'x' }, 1)).toEqual(byRank(inB.filter((n) => n.title === 'x')));
180
+ expect(await walk({ dfolderId: 'fb' }, 50)).toHaveLength(inB.length);
181
+ });
182
+ it('is permission_denied to a caller without the key', async () => {
183
+ expect(await codeOf(asDave.invoke('derived/list-notes', { dfolderId: 'fb' }))).toBe('permission_denied');
184
+ });
185
+ it('answers not_found for a parent that does not exist, and an empty page for one with no rows (#2157)', async () => {
186
+ const list = (who, dfolderId) => who.invoke('derived/list-notes', { dfolderId });
187
+ expect(await codeOf(list(as, 'nope'))).toBe('not_found');
188
+ expect(await messageOf(list(as, 'nope'))).toContain('dfolder not found: nope');
189
+ expect(await list(as, 'fc')).toMatchObject({ entries: [], nextCursor: null, total: 0 });
190
+ // Checked first: a caller without the key learns nothing about whether the parent exists.
191
+ expect(await codeOf(list(asDave, 'nope'))).toBe('permission_denied');
192
+ });
193
+ });
194
+ describe('create (#2157)', () => {
195
+ const create = (who, input) => who.invoke('derived/create-tag', input);
196
+ const getTag = (who, tagId) => who.invoke('derived/get-tag', { tagId });
197
+ const isoNow = (value) => !Number.isNaN(Date.parse(value)) && new Date(value).toISOString() === value;
198
+ /** Neither adapter's fixture moves its clock, so `ctx.now()` is the wall clock around the call. */
199
+ const during = async (call) => {
200
+ const from = new Date().toISOString();
201
+ const result = await call();
202
+ return { result, from, to: new Date().toISOString() };
203
+ };
204
+ it('inserts the row: a minted id, the parent link, the input, NULL for what was left out, the stamps', async () => {
205
+ const { result: tag, from, to } = await during(() => create(as, { dfolderId: 'fa', label: 'red' }));
206
+ expect(tag.created_at >= from && tag.created_at <= to).toBe(true);
207
+ expect(tag).toEqual({
208
+ id: expect.any(String),
209
+ dfolder_id: 'fa',
210
+ label: 'red',
211
+ note: null,
212
+ created_at: expect.any(String),
213
+ created_by: alice,
214
+ });
215
+ expect(isoNow(tag.created_at)).toBe(true);
216
+ expect(tag.id).toMatch(/^[0-9A-HJKMNP-TV-Z]{26}$/);
217
+ expect(await getTag(as, tag.id)).toEqual(tag);
218
+ });
219
+ it('emits one event about the new row, its payload the declared fields as written', async () => {
220
+ const tag = await create(as, { dfolderId: 'fa', label: 'green', note: 'n' });
221
+ const events = (await history(tag.id)).filter((e) => e.type === 'dtag.created');
222
+ expect(events).toHaveLength(1);
223
+ expect(events[0]?.payload).toEqual({
224
+ id: tag.id,
225
+ dfolder_id: 'fa',
226
+ label: 'green',
227
+ created_at: tag.created_at,
228
+ created_by: alice,
229
+ });
230
+ });
231
+ it('answers the row already holding the natural key, unchanged, with no write and no event', async () => {
232
+ const first = await create(as, { dfolderId: 'fa', label: 'blue', note: 'first' });
233
+ const again = await create(asCarl, { dfolderId: 'fa', label: 'blue', note: 'second' });
234
+ expect(again).toEqual(first);
235
+ expect((await history(first.id)).filter((e) => e.type === 'dtag.created')).toHaveLength(1);
236
+ // The key is the pair: the same label under another folder is another row.
237
+ const elsewhere = await create(as, { dfolderId: 'fb', label: 'blue' });
238
+ expect(elsewhere.id).not.toBe(first.id);
239
+ });
240
+ it('answers not_found for a parent that does not exist, and denied first to a caller without the key', async () => {
241
+ expect(await codeOf(create(as, { dfolderId: 'nope', label: 'x' }))).toBe('not_found');
242
+ expect(await messageOf(create(as, { dfolderId: 'nope', label: 'x' }))).toContain('dfolder not found: nope');
243
+ expect(await codeOf(create(asDave, { dfolderId: 'nope', label: 'x' }))).toBe('permission_denied');
244
+ expect(await codeOf(create(asDave, { dfolderId: 'fa', label: 'daves' }))).toBe('permission_denied');
245
+ // Nothing was written by the refusals: the label is still free in that folder.
246
+ expect((await create(as, { dfolderId: 'fa', label: 'daves' })).created_by).toBe(alice);
247
+ });
248
+ it('links the new row to its parent, so a grant on the folder reaches the tag', async () => {
249
+ const reader = principalId.parse(ulid());
250
+ await host.admin.grant(staff, {
251
+ principalId: reader,
252
+ permission: permissionKey.parse('dnote:read'),
253
+ node: { tenantId: t, scopeId: s },
254
+ entity: { entityType: 'dfolder', entityId: 'fa' },
255
+ grantedBy: alice,
256
+ });
257
+ const asReader = await host.getScope(reader, t, s);
258
+ const inA = await create(as, { dfolderId: 'fa', label: 'linked' });
259
+ const inB = await create(as, { dfolderId: 'fb', label: 'linked' });
260
+ expect(await getTag(asReader, inA.id)).toEqual(inA);
261
+ expect(await codeOf(getTag(asReader, inB.id))).toBe('permission_denied');
262
+ });
263
+ // The round-1 review's reproduction (#2162): a key without the folder let a caller holding
264
+ // write on folder A replay folder B's row by guessing its label, and read it in full. Such a
265
+ // declaration no longer loads; the fixture's key includes the link, and stays in its folder.
266
+ it('a natural key without the parent link is refused at load, so a replay cannot cross parents', async () => {
267
+ const crossing = defineEntities({
268
+ folder: { table: 'x_folders', fields: z.object({ id: z.string() }) },
269
+ item: {
270
+ table: 'x_items',
271
+ fields: z.object({ id: z.string(), folder_id: z.string(), label: z.string(), secret: z.string() }),
272
+ parents: ['folder'],
273
+ key: ['label'],
274
+ },
275
+ });
276
+ const declare = () => defineOperations(crossing, ['item:write'])({
277
+ 'x/create-item': {
278
+ summary: 'Add an item',
279
+ derive: 'create',
280
+ permission: { key: 'item:write', entity: 'folder', idFrom: 'folderId' },
281
+ input: z.object({ folderId: z.string(), label: z.string(), secret: z.string() }),
282
+ output: crossing.item.fields,
283
+ http: { method: 'POST', path: '/folders/{folderId}/items' },
284
+ emits: { entity: 'item', entityIdFrom: 'id', type: 'x.item-created', schemaVersion: 1, piiClass: 'none', payload: ['id'] },
285
+ },
286
+ });
287
+ expect(declare).toThrow("its natural key does not include the link to 'folder' ('folder_id')");
288
+ // The twin, on this adapter: the same label in another folder is that folder's own row.
289
+ const inA = await create(as, { dfolderId: 'fa', label: 'payroll', note: 'salaries.xlsx' });
290
+ const inB = await create(asCarl, { dfolderId: 'fb', label: 'payroll', note: 'guess' });
291
+ expect(inB.id).not.toBe(inA.id);
292
+ expect(inB).toMatchObject({ dfolder_id: 'fb', note: 'guess' });
293
+ });
294
+ it('creates scope-wide with no parent, and without a natural key every call is a new row', async () => {
295
+ const one = await as.invoke('derived/create-label', { name: 'same' });
296
+ const two = await as.invoke('derived/create-label', { name: 'same' });
297
+ expect(one).toEqual({ id: expect.any(String), name: 'same' });
298
+ expect(two.id).not.toBe(one.id);
299
+ expect(await codeOf(asDave.invoke('derived/create-label', { name: 'x' }))).toBe('permission_denied');
300
+ });
301
+ it('a derived update by someone else leaves the create stamps as they were', async () => {
302
+ const tag = await create(as, { dfolderId: 'fa', label: 'restamped' });
303
+ const changed = await asCarl.invoke('derived/update-tag', { tagId: tag.id, note: 'by carl' });
304
+ expect(changed).toEqual({ ...tag, note: 'by carl' });
305
+ const events = (await history(tag.id)).filter((e) => e.type === 'dtag.updated');
306
+ expect(events[0]?.payload).toEqual({ id: tag.id, note: 'by carl', created_by: alice });
307
+ });
308
+ });
309
+ describe('archive and trash (#119)', () => {
310
+ const addShelf = async (label) => {
311
+ const id = ulid();
312
+ await as.invoke('derived/add-shelf', { id, label });
313
+ return { id, label };
314
+ };
315
+ const move = (who, verb, shelfId) => who.invoke(`derived/${verb}-shelf`, { shelfId });
316
+ const ids = async (who, op, input = {}) => (await who.invoke(op, { ...input, limit: 100 })).entries.map((r) => r.id);
317
+ const grantOn = (principal, key, shelfId) => host.admin.grant(staff, {
318
+ principalId: principal,
319
+ permission: permissionKey.parse(key),
320
+ node: { tenantId: t, scopeId: s },
321
+ entity: { entityType: 'dshelf', entityId: shelfId },
322
+ grantedBy: alice,
323
+ });
324
+ // The round-3 review's reproduction (#2162): with a natural key, a derived create on a
325
+ // trashable entity replayed a BINNED row — its contents included — to a caller who got
326
+ // `not_found` reading it, and "succeeded" with nothing to show. Such a declaration no
327
+ // longer loads, for `archive` too; without a key the create derives, and is seen.
328
+ it('a keyed derived create over an entity that hides rows is refused at load; without the key it derives', async () => {
329
+ for (const hides of [{ trash: { permission: 'dshelf:trash' } }, { archive: { permission: 'dshelf:archive' } }]) {
330
+ const keyed = defineEntities({
331
+ xshelf: { table: 'x_shelves', fields: z.object({ id: z.string(), label: z.string() }), key: ['label'], ...hides },
332
+ });
333
+ const declare = () => defineOperations(keyed, ['dshelf:write', 'dshelf:trash', 'dshelf:archive'])({
334
+ 'x/create-shelf': {
335
+ summary: 'Add a shelf',
336
+ derive: 'create',
337
+ permission: 'dshelf:write',
338
+ input: z.object({ label: z.string() }),
339
+ output: keyed.xshelf.fields,
340
+ http: { method: 'POST', path: '/shelves' },
341
+ emits: { entity: 'xshelf', entityIdFrom: 'id', type: 'x.shelf-created', schemaVersion: 1, piiClass: 'none', payload: ['id'] },
342
+ },
343
+ });
344
+ expect(declare).toThrow('and a natural key, so a replay could answer a row the kernel hides');
345
+ }
346
+ const made = await as.invoke('derived/create-shelf', { label: 'minted' });
347
+ expect(made).toEqual({ id: expect.any(String), label: 'minted' });
348
+ expect(await ids(as, 'derived/list-shelves')).toContain(made.id);
349
+ await move(as, 'trash', made.id);
350
+ // No key, no replay: the same label again is a new, visible shelf, never the binned one.
351
+ const again = await as.invoke('derived/create-shelf', { label: 'minted' });
352
+ expect(again.id).not.toBe(made.id);
353
+ expect(await ids(as, 'derived/list-shelves')).toEqual(expect.arrayContaining([again.id]));
354
+ expect(await ids(as, 'derived/list-shelves')).not.toContain(made.id);
355
+ });
356
+ it('archives out of the active view and into the archived one, and back', async () => {
357
+ const sh = await addShelf('filed');
358
+ expect(await move(as, 'archive', sh.id)).toEqual({ id: sh.id, state: 'archived' });
359
+ expect(await ids(as, 'derived/list-shelves')).not.toContain(sh.id);
360
+ expect(await ids(as, 'derived/list-shelves', { view: 'archived' })).toContain(sh.id);
361
+ expect(await move(as, 'unarchive', sh.id)).toEqual({ id: sh.id, state: 'active' });
362
+ expect(await ids(as, 'derived/list-shelves')).toContain(sh.id);
363
+ expect(await ids(as, 'derived/list-shelves', { view: 'archived' })).not.toContain(sh.id);
364
+ });
365
+ it('bins out of every view and into the bin, and a restore puts back the archive it came from', async () => {
366
+ const sh = await addShelf('binned');
367
+ await move(as, 'archive', sh.id);
368
+ expect(await move(as, 'trash', sh.id)).toEqual({ id: sh.id, state: 'trashed' });
369
+ expect(await ids(as, 'derived/list-shelves')).not.toContain(sh.id);
370
+ expect(await ids(as, 'derived/list-shelves', { view: 'archived' })).not.toContain(sh.id);
371
+ expect(await ids(as, 'derived/trashed-shelves')).toContain(sh.id);
372
+ expect(await move(as, 'restore', sh.id)).toEqual({ id: sh.id, state: 'archived' });
373
+ expect(await ids(as, 'derived/trashed-shelves')).not.toContain(sh.id);
374
+ });
375
+ it('refuses a move out of the wrong state as conflict, and a missing row as not_found', async () => {
376
+ const sh = await addShelf('twice');
377
+ expect(await codeOf(move(as, 'unarchive', sh.id))).toBe('conflict');
378
+ expect(await codeOf(move(as, 'restore', sh.id))).toBe('conflict');
379
+ await move(as, 'archive', sh.id);
380
+ expect(await codeOf(move(as, 'archive', sh.id))).toBe('conflict');
381
+ expect(await codeOf(move(as, 'archive', 'missing'))).toBe('not_found');
382
+ expect(await codeOf(move(as, 'trash', 'missing'))).toBe('not_found');
383
+ });
384
+ it('lets only restore reach a binned row: the host refuses the other moves as not_found', async () => {
385
+ const sh = await addShelf('gone');
386
+ await move(as, 'trash', sh.id);
387
+ expect(await codeOf(move(as, 'archive', sh.id))).toBe('not_found');
388
+ expect(await codeOf(move(as, 'trash', sh.id))).toBe('not_found');
389
+ expect(await move(as, 'restore', sh.id)).toEqual({ id: sh.id, state: 'active' });
390
+ });
391
+ it('checks each move under its own key: archive authority is not trash authority', async () => {
392
+ const archivist = principalId.parse(ulid());
393
+ const binner = principalId.parse(ulid());
394
+ const a = await addShelf('a');
395
+ await grantOn(archivist, 'dshelf:archive', a.id);
396
+ await grantOn(binner, 'dshelf:trash', a.id);
397
+ const asArchivist = await host.getScope(archivist, t, s);
398
+ const asBinner = await host.getScope(binner, t, s);
399
+ expect(await codeOf(move(asBinner, 'archive', a.id))).toBe('permission_denied');
400
+ expect(await codeOf(move(asArchivist, 'trash', a.id))).toBe('permission_denied');
401
+ expect(await move(asArchivist, 'archive', a.id)).toEqual({ id: a.id, state: 'archived' });
402
+ expect(await move(asBinner, 'trash', a.id)).toEqual({ id: a.id, state: 'trashed' });
403
+ expect(await codeOf(move(asArchivist, 'restore', a.id))).toBe('permission_denied');
404
+ expect(await move(asBinner, 'restore', a.id)).toEqual({ id: a.id, state: 'archived' });
405
+ });
406
+ it('denies a caller without the key first, whether or not the row exists', async () => {
407
+ const sh = await addShelf('guarded');
408
+ for (const verb of ['archive', 'unarchive', 'trash', 'restore']) {
409
+ expect(await codeOf(move(asDave, verb, sh.id))).toBe('permission_denied');
410
+ expect(await codeOf(move(asDave, verb, 'missing'))).toBe('permission_denied');
411
+ }
412
+ });
413
+ it('walks the bin row by row: a trash key narrowed to one row shows that row and no other', async () => {
414
+ const nell = principalId.parse(ulid());
415
+ const mine = await addShelf('mine');
416
+ const theirs = await addShelf('theirs');
417
+ await move(as, 'trash', mine.id);
418
+ await move(as, 'trash', theirs.id);
419
+ await grantOn(nell, 'dshelf:trash', mine.id);
420
+ const asNell = await host.getScope(nell, t, s);
421
+ // A scope-wide check in front of the walk would deny nell outright.
422
+ const seen = await ids(asNell, 'derived/trashed-shelves');
423
+ expect(seen).toContain(mine.id);
424
+ expect(seen).not.toContain(theirs.id);
425
+ expect(await ids(as, 'derived/trashed-shelves')).toEqual(expect.arrayContaining([mine.id, theirs.id]));
426
+ expect(await ids(asDave, 'derived/trashed-shelves')).toEqual([]);
427
+ });
428
+ });
429
+ // The check is on the entity the declaration names, not the scope: a principal holding the
430
+ // key on ONE row (or one parent) reaches that row and no other. A check that dropped the
431
+ // entity would deny the twins below, since an entity-narrowed grant is no node-level grant.
432
+ describe('entity-narrowed grants', () => {
433
+ const nina = principalId.parse(ulid());
434
+ const fran = principalId.parse(ulid());
435
+ let asNina;
436
+ let asFran;
437
+ let n1;
438
+ let n2;
439
+ const narrow = (principal, key, entityType, entityId) => host.admin.grant(staff, {
440
+ principalId: principal,
441
+ permission: permissionKey.parse(key),
442
+ node: { tenantId: t, scopeId: s },
443
+ entity: { entityType, entityId },
444
+ grantedBy: alice,
445
+ });
446
+ const update = (who, noteId, title) => who.invoke('derived/update-note', { noteId, title });
447
+ const del = (who, noteId) => who.invoke('derived/delete-note', { noteId });
448
+ const list = (who, folderId) => who.invoke('derived/list-notes', { dfolderId: folderId, limit: 50 });
449
+ beforeAll(async () => {
450
+ n1 = await addNote('fa', 'mine', 61);
451
+ n2 = await addNote('fa', 'theirs', 62);
452
+ await narrow(nina, 'dnote:read', 'dnote', n1.id);
453
+ await narrow(nina, 'dnote:write', 'dnote', n1.id);
454
+ await narrow(fran, 'dnote:read', 'dfolder', 'fa');
455
+ asNina = await host.getScope(nina, t, s);
456
+ asFran = await host.getScope(fran, t, s);
457
+ });
458
+ it('get: the granted row answers, its sibling is denied', async () => {
459
+ expect(await get(asNina, n1.id)).toEqual(n1);
460
+ expect(await codeOf(get(asNina, n2.id))).toBe('permission_denied');
461
+ });
462
+ it('update: the granted row is written, its sibling is denied and left alone', async () => {
463
+ expect((await update(asNina, n1.id, 'mine, edited')).title).toBe('mine, edited');
464
+ expect(await codeOf(update(asNina, n2.id, 'not yours'))).toBe('permission_denied');
465
+ expect(await get(as, n2.id)).toEqual(n2);
466
+ });
467
+ it('delete: the sibling is denied and stays, the granted row goes', async () => {
468
+ expect(await codeOf(del(asNina, n2.id))).toBe('permission_denied');
469
+ expect(await get(as, n2.id)).toEqual(n2);
470
+ expect(await del(asNina, n1.id)).toEqual({ id: n1.id, deleted: true });
471
+ });
472
+ it('list: the granted folder pages, the other folder is denied', async () => {
473
+ const page = await list(asFran, 'fa');
474
+ expect(page.entries.map((n) => n.id)).toContain(n2.id);
475
+ expect(page.entries.every((n) => n.dfolder_id === 'fa')).toBe(true);
476
+ expect(await codeOf(list(asFran, 'fb'))).toBe('permission_denied');
477
+ });
478
+ });
479
+ });
480
+ }
481
+ //# sourceMappingURL=derived-suite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derived-suite.js","sourceRoot":"","sources":["../src/derived-suite.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"entity-state-module.d.ts","sourceRoot":"","sources":["../src/entity-state-module.ts"],"names":[],"mappings":"AAaA,OAAO,EAIL,KAAK,kBAAkB,EAExB,MAAM,sBAAsB,CAAC;AAE9B,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6B3B,CAAC;AAQH,eAAO,MAAM,QAAQ,EAAE,kBA2FtB,CAAC;AAWF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyB7B,CAAC;AAQH,eAAO,MAAM,UAAU,EAAE,kBAgFxB,CAAC"}
1
+ {"version":3,"file":"entity-state-module.d.ts","sourceRoot":"","sources":["../src/entity-state-module.ts"],"names":[],"mappings":"AAaA,OAAO,EAML,KAAK,kBAAkB,EAExB,MAAM,sBAAsB,CAAC;AAG9B,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6B3B,CAAC;AAcH,eAAO,MAAM,QAAQ,EAAE,kBA2FtB,CAAC;AAWF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyB7B,CAAC;AAQH,eAAO,MAAM,UAAU,EAAE,kBAgFxB,CAAC"}
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import { moduleManifest, operationInputsOf } from '@substrat-run/contracts';
14
14
  import { listIndexPlans, listQuery, readHistory, } from '@substrat-run/kernel';
15
+ import { testOperations } from './test-operations.js';
15
16
  export const stateModManifest = moduleManifest.parse({
16
17
  id: '@test/state',
17
18
  version: '1.0.0',
@@ -46,6 +47,11 @@ const ref = (input) => {
46
47
  const i = input;
47
48
  return { entityType: i.entityType ?? 'stdoc', entityId: i.id };
48
49
  };
50
+ /** These handlers, each declared with no input and no entity-narrowed check (#119 PR 2). */
51
+ function declaredWithNoInput(handlers) {
52
+ const inputs = operationInputsOf(Object.fromEntries(Object.keys(handlers).map((name) => [name, {}])));
53
+ return testOperations(handlers, { inputs }).operations;
54
+ }
49
55
  export const stateMod = {
50
56
  manifest: stateModManifest,
51
57
  migrations: [
@@ -56,7 +62,7 @@ export const stateMod = {
56
62
  CREATE TABLE state_plain (id TEXT PRIMARY KEY, title TEXT NOT NULL);`,
57
63
  },
58
64
  ],
59
- operations: {
65
+ ...testOperations({
60
66
  'state/add': (async (ctx, input) => {
61
67
  const i = input;
62
68
  const table = { stdoc: 'state_docs', stnote: 'state_notes', stplain: 'state_plain' }[i.entityType ?? 'stdoc'];
@@ -135,7 +141,7 @@ export const stateMod = {
135
141
  .query(`EXPLAIN QUERY PLAN ${q.sql}`, q.params)
136
142
  .map((row) => row.detail);
137
143
  }),
138
- },
144
+ }),
139
145
  };
140
146
  /**
141
147
  * #119 PR 2: every operation above declared, each with no input and no entity-narrowed check. They
@@ -144,7 +150,7 @@ export const stateMod = {
144
150
  * trashable module must declare everything it binds, so this one says, in the host's terms, that
145
151
  * none of them addresses an entity by id.
146
152
  */
147
- stateMod.operationInputs = operationInputsOf(Object.fromEntries(Object.keys(stateMod.operations).map((name) => [name, {}])));
153
+ stateMod.operations = declaredWithNoInput(stateMod.operations.handlers);
148
154
  /**
149
155
  * The fixture behind `entityStateMigrationContractSuite` (#2090): authored migrations that
150
156
  * REBUILD a table, the create-copy-rename SQLite needs for a column type change or a dropped
@@ -239,7 +245,7 @@ export const rebuildMod = {
239
245
  ALTER TABLE rb_search_new RENAME TO rb_search;`,
240
246
  },
241
247
  ],
242
- operations: {
248
+ ...testOperations({
243
249
  'rb/add': (async (ctx, input) => {
244
250
  const i = input;
245
251
  ctx.sql.exec(`INSERT INTO ${RB_TABLES[i.entityType]} (id, title) VALUES (?, ?)`, [i.id, i.title]);
@@ -271,8 +277,8 @@ export const rebuildMod = {
271
277
  'rb/titles': (async (ctx, input) => ctx.sql
272
278
  .query(`SELECT title FROM ${RB_TABLES[input.entityType]} ORDER BY title`)
273
279
  .map((r) => r.title)),
274
- },
280
+ }),
275
281
  };
276
282
  /** Its operations declared the same way as `stateMod`'s, so a trashable module registers (#119). */
277
- rebuildMod.operationInputs = operationInputsOf(Object.fromEntries(Object.keys(rebuildMod.operations).map((name) => [name, {}])));
283
+ rebuildMod.operations = declaredWithNoInput(rebuildMod.operations.handlers);
278
284
  //# sourceMappingURL=entity-state-module.js.map