@byline/core 3.7.0 → 3.8.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.
@@ -415,6 +415,8 @@ export interface IDocumentCommands {
415
415
  documentId: string;
416
416
  locale: string;
417
417
  status?: string;
418
+ /** Acting user id for the version audit trail (`created_by`). See docs/AUDIT.md. */
419
+ createdBy?: string;
418
420
  }): Promise<{
419
421
  newVersionId: string;
420
422
  previousVersionId: string;
@@ -12,6 +12,8 @@ export declare const createBaseSchema: (collection?: CollectionDefinition) => z.
12
12
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
13
13
  createdAt: z.ZodISODateTime;
14
14
  updatedAt: z.ZodISODateTime;
15
+ createdBy: z.ZodOptional<z.ZodUUID>;
16
+ eventType: z.ZodOptional<z.ZodString>;
15
17
  }, z.core.$strip>;
16
18
  export declare const createFieldsSchema: (fields: Field[], strict?: boolean) => z.ZodObject<{
17
19
  [x: string]: z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>;
@@ -44,6 +46,8 @@ export declare const createCollectionSchemasForPath: (path: string) => {
44
46
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
45
47
  createdAt: z.ZodISODateTime;
46
48
  updatedAt: z.ZodISODateTime;
49
+ createdBy: z.ZodOptional<z.ZodUUID>;
50
+ eventType: z.ZodOptional<z.ZodString>;
47
51
  }, z.core.$strip>;
48
52
  fields: z.ZodObject<{
49
53
  [x: string]: z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>;
@@ -62,6 +66,8 @@ export declare const createCollectionSchemasForPath: (path: string) => {
62
66
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
63
67
  createdAt: z.ZodISODateTime;
64
68
  updatedAt: z.ZodISODateTime;
69
+ createdBy: z.ZodOptional<z.ZodUUID>;
70
+ eventType: z.ZodOptional<z.ZodString>;
65
71
  }, z.core.$strip>;
66
72
  list: z.ZodObject<{
67
73
  docs: z.ZodArray<z.ZodObject<{
@@ -78,6 +84,8 @@ export declare const createCollectionSchemasForPath: (path: string) => {
78
84
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
79
85
  createdAt: z.ZodISODateTime;
80
86
  updatedAt: z.ZodISODateTime;
87
+ createdBy: z.ZodOptional<z.ZodUUID>;
88
+ eventType: z.ZodOptional<z.ZodString>;
81
89
  }, z.core.$strip>>;
82
90
  meta: z.ZodObject<{
83
91
  page: z.ZodNumber;
@@ -113,6 +121,8 @@ export declare const createCollectionSchemasForPath: (path: string) => {
113
121
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
114
122
  createdAt: z.ZodISODateTime;
115
123
  updatedAt: z.ZodISODateTime;
124
+ createdBy: z.ZodOptional<z.ZodUUID>;
125
+ eventType: z.ZodOptional<z.ZodString>;
116
126
  }, z.core.$strip>>;
117
127
  meta: z.ZodObject<{
118
128
  page: z.ZodNumber;
@@ -140,6 +150,8 @@ export declare const createCollectionSchemasForPath: (path: string) => {
140
150
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
141
151
  createdAt: z.ZodISODateTime;
142
152
  updatedAt: z.ZodISODateTime;
153
+ createdBy: z.ZodOptional<z.ZodUUID>;
154
+ eventType: z.ZodOptional<z.ZodString>;
143
155
  }, z.core.$strip>;
144
156
  update: z.ZodObject<{
145
157
  [x: string]: z.ZodOptional<z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>>;
@@ -157,6 +169,8 @@ export declare const createCollectionSchemas: (collection: CollectionDefinition)
157
169
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
158
170
  createdAt: z.ZodISODateTime;
159
171
  updatedAt: z.ZodISODateTime;
172
+ createdBy: z.ZodOptional<z.ZodUUID>;
173
+ eventType: z.ZodOptional<z.ZodString>;
160
174
  }, z.core.$strip>;
161
175
  fields: z.ZodObject<{
162
176
  [x: string]: z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>;
@@ -175,6 +189,8 @@ export declare const createCollectionSchemas: (collection: CollectionDefinition)
175
189
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
176
190
  createdAt: z.ZodISODateTime;
177
191
  updatedAt: z.ZodISODateTime;
192
+ createdBy: z.ZodOptional<z.ZodUUID>;
193
+ eventType: z.ZodOptional<z.ZodString>;
178
194
  }, z.core.$strip>;
179
195
  list: z.ZodObject<{
180
196
  docs: z.ZodArray<z.ZodObject<{
@@ -191,6 +207,8 @@ export declare const createCollectionSchemas: (collection: CollectionDefinition)
191
207
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
192
208
  createdAt: z.ZodISODateTime;
193
209
  updatedAt: z.ZodISODateTime;
210
+ createdBy: z.ZodOptional<z.ZodUUID>;
211
+ eventType: z.ZodOptional<z.ZodString>;
194
212
  }, z.core.$strip>>;
195
213
  meta: z.ZodObject<{
196
214
  page: z.ZodNumber;
@@ -226,6 +244,8 @@ export declare const createCollectionSchemas: (collection: CollectionDefinition)
226
244
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
227
245
  createdAt: z.ZodISODateTime;
228
246
  updatedAt: z.ZodISODateTime;
247
+ createdBy: z.ZodOptional<z.ZodUUID>;
248
+ eventType: z.ZodOptional<z.ZodString>;
229
249
  }, z.core.$strip>>;
230
250
  meta: z.ZodObject<{
231
251
  page: z.ZodNumber;
@@ -253,6 +273,8 @@ export declare const createCollectionSchemas: (collection: CollectionDefinition)
253
273
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
254
274
  createdAt: z.ZodISODateTime;
255
275
  updatedAt: z.ZodISODateTime;
276
+ createdBy: z.ZodOptional<z.ZodUUID>;
277
+ eventType: z.ZodOptional<z.ZodString>;
256
278
  }, z.core.$strip>;
257
279
  update: z.ZodObject<{
258
280
  [x: string]: z.ZodOptional<z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>>;
@@ -270,6 +292,8 @@ export declare const createTypedCollectionSchemas: (collection: CollectionDefini
270
292
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
271
293
  createdAt: z.ZodISODateTime;
272
294
  updatedAt: z.ZodISODateTime;
295
+ createdBy: z.ZodOptional<z.ZodUUID>;
296
+ eventType: z.ZodOptional<z.ZodString>;
273
297
  }, z.core.$strip>;
274
298
  fields: z.ZodObject<{
275
299
  [x: string]: z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>;
@@ -288,6 +312,8 @@ export declare const createTypedCollectionSchemas: (collection: CollectionDefini
288
312
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
289
313
  createdAt: z.ZodISODateTime;
290
314
  updatedAt: z.ZodISODateTime;
315
+ createdBy: z.ZodOptional<z.ZodUUID>;
316
+ eventType: z.ZodOptional<z.ZodString>;
291
317
  }, z.core.$strip>;
292
318
  list: z.ZodObject<{
293
319
  docs: z.ZodArray<z.ZodObject<{
@@ -304,6 +330,8 @@ export declare const createTypedCollectionSchemas: (collection: CollectionDefini
304
330
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
305
331
  createdAt: z.ZodISODateTime;
306
332
  updatedAt: z.ZodISODateTime;
333
+ createdBy: z.ZodOptional<z.ZodUUID>;
334
+ eventType: z.ZodOptional<z.ZodString>;
307
335
  }, z.core.$strip>>;
308
336
  meta: z.ZodObject<{
309
337
  page: z.ZodNumber;
@@ -339,6 +367,8 @@ export declare const createTypedCollectionSchemas: (collection: CollectionDefini
339
367
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
340
368
  createdAt: z.ZodISODateTime;
341
369
  updatedAt: z.ZodISODateTime;
370
+ createdBy: z.ZodOptional<z.ZodUUID>;
371
+ eventType: z.ZodOptional<z.ZodString>;
342
372
  }, z.core.$strip>>;
343
373
  meta: z.ZodObject<{
344
374
  page: z.ZodNumber;
@@ -366,6 +396,8 @@ export declare const createTypedCollectionSchemas: (collection: CollectionDefini
366
396
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
367
397
  createdAt: z.ZodISODateTime;
368
398
  updatedAt: z.ZodISODateTime;
399
+ createdBy: z.ZodOptional<z.ZodUUID>;
400
+ eventType: z.ZodOptional<z.ZodString>;
369
401
  }, z.core.$strip>;
370
402
  update: z.ZodObject<{
371
403
  [x: string]: z.ZodOptional<z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>>;
@@ -383,6 +415,8 @@ export declare const createTypedCollectionSchemasForPath: (path: string) => {
383
415
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
384
416
  createdAt: z.ZodISODateTime;
385
417
  updatedAt: z.ZodISODateTime;
418
+ createdBy: z.ZodOptional<z.ZodUUID>;
419
+ eventType: z.ZodOptional<z.ZodString>;
386
420
  }, z.core.$strip>;
387
421
  fields: z.ZodObject<{
388
422
  [x: string]: z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>;
@@ -401,6 +435,8 @@ export declare const createTypedCollectionSchemasForPath: (path: string) => {
401
435
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
402
436
  createdAt: z.ZodISODateTime;
403
437
  updatedAt: z.ZodISODateTime;
438
+ createdBy: z.ZodOptional<z.ZodUUID>;
439
+ eventType: z.ZodOptional<z.ZodString>;
404
440
  }, z.core.$strip>;
405
441
  list: z.ZodObject<{
406
442
  docs: z.ZodArray<z.ZodObject<{
@@ -417,6 +453,8 @@ export declare const createTypedCollectionSchemasForPath: (path: string) => {
417
453
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
418
454
  createdAt: z.ZodISODateTime;
419
455
  updatedAt: z.ZodISODateTime;
456
+ createdBy: z.ZodOptional<z.ZodUUID>;
457
+ eventType: z.ZodOptional<z.ZodString>;
420
458
  }, z.core.$strip>>;
421
459
  meta: z.ZodObject<{
422
460
  page: z.ZodNumber;
@@ -452,6 +490,8 @@ export declare const createTypedCollectionSchemasForPath: (path: string) => {
452
490
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
453
491
  createdAt: z.ZodISODateTime;
454
492
  updatedAt: z.ZodISODateTime;
493
+ createdBy: z.ZodOptional<z.ZodUUID>;
494
+ eventType: z.ZodOptional<z.ZodString>;
455
495
  }, z.core.$strip>>;
456
496
  meta: z.ZodObject<{
457
497
  page: z.ZodNumber;
@@ -479,6 +519,8 @@ export declare const createTypedCollectionSchemasForPath: (path: string) => {
479
519
  hasPublishedVersion: z.ZodOptional<z.ZodBoolean>;
480
520
  createdAt: z.ZodISODateTime;
481
521
  updatedAt: z.ZodISODateTime;
522
+ createdBy: z.ZodOptional<z.ZodUUID>;
523
+ eventType: z.ZodOptional<z.ZodString>;
482
524
  }, z.core.$strip>;
483
525
  update: z.ZodObject<{
484
526
  [x: string]: z.ZodOptional<z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>>;
@@ -205,6 +205,11 @@ export const createBaseSchema = (collection) => {
205
205
  hasPublishedVersion: z.boolean().optional(),
206
206
  createdAt: z.iso.datetime(),
207
207
  updatedAt: z.iso.datetime(),
208
+ // Version audit metadata — acting user + action (see docs/AUDIT.md — Workstream 1).
209
+ // Declared so list/get/history responses carry them through the
210
+ // server-fn parse; Zod would otherwise strip them as undeclared keys.
211
+ createdBy: z.uuid().optional(),
212
+ eventType: z.string().optional(),
208
213
  });
209
214
  };
210
215
  // Create field schemas for a collection.
@@ -10,7 +10,7 @@ import { assertActorCanPerform } from '../../auth/assert-actor-can-perform.js';
10
10
  import { ERR_NOT_FOUND, ERR_VALIDATION } from '../../lib/errors.js';
11
11
  import { withLogContext } from '../../lib/logger.js';
12
12
  import { getDefaultStatus } from '../../workflow/workflow.js';
13
- import { applyRichTextEmbed, extractVersionId, invokeHook } from './internals.js';
13
+ import { actorId, applyRichTextEmbed, extractVersionId, invokeHook } from './internals.js';
14
14
  import { mergeLocaleData } from './merge-locale-data.js';
15
15
  /**
16
16
  * Copy a document's content from one locale into another, in place on
@@ -133,6 +133,7 @@ export async function copyToLocale(ctx, params) {
133
133
  status: getDefaultStatus(definition),
134
134
  locale: params.targetLocale,
135
135
  previousVersionId,
136
+ createdBy: actorId(ctx),
136
137
  });
137
138
  const documentVersionId = extractVersionId(writeResult.document);
138
139
  await invokeHook(hooks?.afterUpdate, {
@@ -13,7 +13,7 @@ import { normaliseDateFields } from '../../utils/normalise-dates.js';
13
13
  import { slugify } from '../../utils/slugify.js';
14
14
  import { getDefaultStatus } from '../../workflow/workflow.js';
15
15
  import { assignCounterValues } from '../assign-counter-values.js';
16
- import { applyRichTextEmbed, derivePath, extractDocumentId, extractVersionId, invokeHook, maybeAppendOrderKey, rethrowPathConflict, } from './internals.js';
16
+ import { actorId, applyRichTextEmbed, derivePath, extractDocumentId, extractVersionId, invokeHook, maybeAppendOrderKey, rethrowPathConflict, } from './internals.js';
17
17
  /**
18
18
  * Create a new document.
19
19
  *
@@ -75,6 +75,7 @@ export async function createDocument(ctx, params) {
75
75
  status: params.status ?? data.status ?? getDefaultStatus(definition),
76
76
  locale: params.locale ?? defaultLocale,
77
77
  orderKey,
78
+ createdBy: actorId(ctx),
78
79
  })
79
80
  .catch((err) => rethrowPathConflict(err, resolvedPath, defaultLocale));
80
81
  const documentId = extractDocumentId(result.document);
@@ -10,7 +10,7 @@ import { assertActorCanPerform } from '../../auth/assert-actor-can-perform.js';
10
10
  import { ERR_NOT_FOUND, ERR_VALIDATION } from '../../lib/errors.js';
11
11
  import { withLogContext } from '../../lib/logger.js';
12
12
  import { getDefaultStatus } from '../../workflow/workflow.js';
13
- import { invokeHook } from './internals.js';
13
+ import { actorId, invokeHook } from './internals.js';
14
14
  /**
15
15
  * Remove one content locale's data from a document, in place on the same
16
16
  * document, by writing a new immutable version that omits that locale's
@@ -90,6 +90,7 @@ export async function deleteLocale(ctx, params) {
90
90
  documentId: params.documentId,
91
91
  locale: params.locale,
92
92
  status: getDefaultStatus(definition),
93
+ createdBy: actorId(ctx),
93
94
  });
94
95
  if (result == null) {
95
96
  throw ERR_NOT_FOUND({
@@ -12,7 +12,7 @@ import { withLogContext } from '../../lib/logger.js';
12
12
  import { slugify } from '../../utils/slugify.js';
13
13
  import { getDefaultStatus } from '../../workflow/workflow.js';
14
14
  import { assignCounterValues } from '../assign-counter-values.js';
15
- import { applyRichTextEmbed, derivePath, extractDocumentId, extractVersionId, invokeHook, isPathConflictError, maybeAppendOrderKey, rethrowPathConflict, stripMetaIdsInPlace, } from './internals.js';
15
+ import { actorId, applyRichTextEmbed, derivePath, extractDocumentId, extractVersionId, invokeHook, isPathConflictError, maybeAppendOrderKey, rethrowPathConflict, stripMetaIdsInPlace, } from './internals.js';
16
16
  /**
17
17
  * Apply the `" (copy)"` suffix to the configured `useAsTitle` field on a
18
18
  * duplicate's data tree. Handles both shapes:
@@ -170,6 +170,7 @@ export async function duplicateDocument(ctx, params) {
170
170
  status: defaultStatus,
171
171
  locale: 'all',
172
172
  orderKey,
173
+ createdBy: actorId(ctx),
173
174
  })
174
175
  .catch((err) => rethrowPathConflict(err, finalPath, defaultLocale));
175
176
  }
@@ -194,6 +195,7 @@ export async function duplicateDocument(ctx, params) {
194
195
  status: defaultStatus,
195
196
  locale: 'all',
196
197
  orderKey,
198
+ createdBy: actorId(ctx),
197
199
  })
198
200
  .catch((retryErr) => rethrowPathConflict(retryErr, finalPath, defaultLocale));
199
201
  }
@@ -15,6 +15,14 @@ import { type CollectionDefinition, type CollectionHookSlot } from '../../@types
15
15
  import type { BylineLogger } from '../../lib/logger.js';
16
16
  import type { SlugifierFn } from '../../utils/slugify.js';
17
17
  import type { DocumentLifecycleContext } from './context.js';
18
+ /**
19
+ * The acting user's id for the version audit trail (`created_by` on
20
+ * `byline_document_versions`). `undefined` for internal-tooling callers
21
+ * without a `requestContext` (seeds, migrations — the documented escape
22
+ * hatch), which persists as NULL. Both actor realms (`AdminAuth`,
23
+ * `UserAuth`) carry `id`. See docs/AUDIT.md — Workstream 1.
24
+ */
25
+ export declare function actorId(ctx: DocumentLifecycleContext): string | undefined;
18
26
  /**
19
27
  * Safely invoke an optional hook slot, awaiting the result if it returns a
20
28
  * Promise. When the slot is an array of functions they are executed
@@ -17,6 +17,16 @@ import { ERR_PATH_CONFLICT, ErrorCodes } from '../../lib/errors.js';
17
17
  import { generateKeyBetween } from '../../lib/fractional-index.js';
18
18
  import { createReadContext } from '../populate.js';
19
19
  import { embedRichTextFields } from '../richtext-embed.js';
20
+ /**
21
+ * The acting user's id for the version audit trail (`created_by` on
22
+ * `byline_document_versions`). `undefined` for internal-tooling callers
23
+ * without a `requestContext` (seeds, migrations — the documented escape
24
+ * hatch), which persists as NULL. Both actor realms (`AdminAuth`,
25
+ * `UserAuth`) carry `id`. See docs/AUDIT.md — Workstream 1.
26
+ */
27
+ export function actorId(ctx) {
28
+ return ctx.requestContext?.actor?.id;
29
+ }
20
30
  /**
21
31
  * Safely invoke an optional hook slot, awaiting the result if it returns a
22
32
  * Promise. When the slot is an array of functions they are executed
@@ -10,7 +10,7 @@ import { assertActorCanPerform } from '../../auth/assert-actor-can-perform.js';
10
10
  import { ERR_INVALID_TRANSITION, ERR_NOT_FOUND, ERR_VALIDATION } from '../../lib/errors.js';
11
11
  import { withLogContext } from '../../lib/logger.js';
12
12
  import { getDefaultStatus } from '../../workflow/workflow.js';
13
- import { applyRichTextEmbed, extractDocumentId, extractVersionId, invokeHook } from './internals.js';
13
+ import { actorId, applyRichTextEmbed, extractDocumentId, extractVersionId, invokeHook, } from './internals.js';
14
14
  /**
15
15
  * Restore a historical document version as the new current version.
16
16
  *
@@ -139,6 +139,7 @@ export async function restoreDocumentVersion(ctx, params) {
139
139
  status: getDefaultStatus(definition),
140
140
  locale: 'all',
141
141
  previousVersionId: currentMeta.document_version_id,
142
+ createdBy: actorId(ctx),
142
143
  });
143
144
  const documentId = extractDocumentId(result.document) || params.documentId;
144
145
  const documentVersionId = extractVersionId(result.document);
@@ -13,7 +13,7 @@ import { applyPatches } from '../../patches/index.js';
13
13
  import { normaliseDateFields } from '../../utils/normalise-dates.js';
14
14
  import { getDefaultStatus } from '../../workflow/workflow.js';
15
15
  import { assignCounterValues } from '../assign-counter-values.js';
16
- import { applyRichTextEmbed, extractDocumentId, extractVersionId, invokeHook, resolvePathForUpdate, rethrowPathConflict, } from './internals.js';
16
+ import { actorId, applyRichTextEmbed, extractDocumentId, extractVersionId, invokeHook, resolvePathForUpdate, rethrowPathConflict, } from './internals.js';
17
17
  /**
18
18
  * Update a document via full replacement (PUT semantics).
19
19
  *
@@ -85,6 +85,7 @@ export async function updateDocument(ctx, params) {
85
85
  status: defaultStatus,
86
86
  locale: requestLocale,
87
87
  previousVersionId: originalData.document_version_id,
88
+ createdBy: actorId(ctx),
88
89
  })
89
90
  .catch((err) => rethrowPathConflict(err, pathForCommand ?? '', defaultLocale));
90
91
  const documentId = extractDocumentId(result.document) || params.documentId;
@@ -198,6 +199,7 @@ export async function updateDocumentWithPatches(ctx, params) {
198
199
  status: defaultStatus,
199
200
  locale: requestLocale,
200
201
  previousVersionId: originalData.document_version_id,
202
+ createdBy: actorId(ctx),
201
203
  })
202
204
  .catch((err) => rethrowPathConflict(err, pathForCommand ?? '', defaultLocale));
203
205
  const documentId = extractDocumentId(result.document) || params.documentId;
@@ -139,6 +139,17 @@ describe('Document lifecycle service', () => {
139
139
  expect(result.documentId).toBe('doc-1');
140
140
  expect(result.documentVersionId).toBe('ver-1');
141
141
  });
142
+ it('passes the acting user id as createdBy for the audit trail', async () => {
143
+ const { db, createDocumentVersion } = createMockDb();
144
+ const ctx = buildCtx(db);
145
+ await createDocument(ctx, {
146
+ data: { title: 'Hello' },
147
+ locale: 'en',
148
+ });
149
+ // Audit contract (docs/AUDIT.md — W1): every version row
150
+ // records the actor that created it.
151
+ expect(createDocumentVersion.mock.calls[0]?.[0].createdBy).toBe('test-super-admin');
152
+ });
142
153
  it('invokes beforeCreate and afterCreate hooks in order', async () => {
143
154
  const callOrder = [];
144
155
  const hooks = {
@@ -307,6 +318,16 @@ describe('Document lifecycle service', () => {
307
318
  // updateDocument (PUT)
308
319
  // -----------------------------------------------------------------------
309
320
  describe('updateDocument', () => {
321
+ it('passes the acting user id as createdBy for the audit trail', async () => {
322
+ const { db, getDocumentById, createDocumentVersion } = createMockDb();
323
+ getDocumentById.mockResolvedValue({ status: 'draft', fields: { title: 'Old' } });
324
+ const ctx = buildCtx(db);
325
+ await updateDocument(ctx, {
326
+ documentId: 'doc-1',
327
+ data: { title: 'New' },
328
+ });
329
+ expect(createDocumentVersion.mock.calls[0]?.[0].createdBy).toBe('test-super-admin');
330
+ });
310
331
  it('fetches the original before calling hooks', async () => {
311
332
  const { db, getDocumentById, createDocumentVersion } = createMockDb();
312
333
  getDocumentById.mockResolvedValue({ status: 'draft', fields: { title: 'Old' } });
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@byline/core",
3
3
  "private": false,
4
4
  "license": "MPL-2.0",
5
- "version": "3.7.0",
5
+ "version": "3.8.0",
6
6
  "engines": {
7
7
  "node": ">=20.9.0"
8
8
  },
@@ -79,7 +79,7 @@
79
79
  "sharp": "^0.34.5",
80
80
  "uuid": "^14.0.0",
81
81
  "zod": "^4.4.3",
82
- "@byline/auth": "3.7.0"
82
+ "@byline/auth": "3.8.0"
83
83
  },
84
84
  "devDependencies": {
85
85
  "@biomejs/biome": "2.4.15",