@forumone/throughline-publishing 0.3.1 → 0.3.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @forumone/throughline-publishing
2
2
 
3
+ ## 0.3.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 4eeb721: Fix published documents being uneditable: allow draft writes through the trust boundary.
8
+
9
+ Editing an already-published document failed with `Direct writes to _status are not allowed` — from both the plugin's own Publish button and Payload's native Save Draft, which discarded the editor's work. Only first publishes worked, because an unmodified document skips the draft save.
10
+
11
+ Payload sets `data._status = 'draft'` on every `draft: true` update _before_ `beforeChange` runs, whether or not the caller supplied it. By the time the hook saw the write, saving a draft of a published document was indistinguishable from unpublishing it: `data._status` was `'draft'` and `originalDoc._status` was `'published'` in both cases. A draft save writes a version and leaves the live document alone, so it should never have been blocked.
12
+
13
+ The plugin now installs a `beforeOperation` hook that records the operation's own `draft` argument, which `beforeChange` reads to tell the two apart. That argument is visible identically on the Local API, REST and GraphQL, unlike `req.query.draft`, which is only populated on the REST path.
14
+
15
+ A `draft: true` request that sets `_status: 'published'` is still blocked — Payload's own `isSavingDraft` excludes it, so it is a real publish and belongs in the pipeline. Genuine unpublishes and direct publishes are unchanged. Installing the status-write hook without the recorder fails closed.
16
+
17
+ - 4eeb721: Fix two defects reported against 0.3.0.
18
+
19
+ **The `alt-text` check false-positived on Payload upload derivatives.** `walkForImages` descended into a populated upload's `sizes` map, and every generated size carries `filename` and `mimeType` but never `alt` — that lives on the parent document. Each configured `imageSize` therefore produced one false failure, and any page carrying a sized image could not be published. The walk now skips `sizes` on an object that is itself an image; alt text is checked once, on the parent. A parent with missing or empty alt still fails, at the parent's path, and a host with no `imageSizes` is unaffected.
20
+
21
+ **A failed Inngest emission failed a publish that had already succeeded.** The event is sent after the document is written, so a transport failure (an invalid `INNGEST_EVENT_KEY`, say) returned 500 for a document that was published — and lost the audit record for it. Publish, unpublish, rollback and `schedule_publish` now report success and carry the emission failure as a `warnings` array on the result. The admin renders it as a warning toast on an otherwise successful publish.
22
+
23
+ Also adds `disableAccessibilityChecks`, naming built-in checks to skip. `accessibilityChecks` only appends, so previously a built-in that misfired on a host's content shape blocked every publish until the plugin shipped a fix.
24
+
3
25
  ## 0.3.1
4
26
 
5
27
  ### Patch Changes
package/README.md CHANGED
@@ -96,6 +96,25 @@ if (!result.published) {
96
96
 
97
97
  All three run the same pipeline the admin and MCP paths use, so host code cannot drift from the plugin's policy. `getPublishStatus` runs every check except the write and mutates nothing.
98
98
 
99
+ ## What the trust boundary blocks
100
+
101
+ The plugin installs two hooks on every configured collection, and they work as a pair:
102
+
103
+ - `beforeOperation` records whether the update in flight is a draft write.
104
+ - `beforeChange` rejects writes that change the **live** document's `_status`.
105
+
106
+ | Write | Result |
107
+ |---|---|
108
+ | `draft: true` on a draft or published document | **allowed** — writes a version, live status unchanged |
109
+ | `draft: false`, `_status: 'published'` | **blocked** — publish through the pipeline |
110
+ | `draft: false`, `_status: 'draft'` on a published document | **blocked** — unpublish through the pipeline |
111
+ | `draft: true` with `_status: 'published'` | **blocked** — Payload treats this as a publish, not a draft save |
112
+ | Any write carrying `bypassPublishingServer` | **allowed** |
113
+
114
+ Draft saves have to be allowed explicitly because Payload sets `data._status = 'draft'` on every `draft: true` update before `beforeChange` runs, whether or not the caller supplied it — so at that point a draft save of a published document and an unpublish look identical. The `draft` flag is read from the operation's own arguments in `beforeOperation`, which sees it the same way on the Local API, REST and GraphQL. (`req.query.draft` is only populated on the REST path, so keying on the request would cover the admin and silently miss scripts.)
115
+
116
+ If you install `createBlockStatusWritesHook` yourself without the recorder, it fails closed: every status change is blocked.
117
+
99
118
  ## Bypassing the pipeline
100
119
 
101
120
  `bypassPublishingServer: true` in the Payload request context is the only way to write `_status` without the pipeline. It is intended for seed scripts and migrations:
@@ -1 +1 @@
1
- {"version":3,"file":"PublishButton.d.ts","sourceRoot":"","sources":["../../src/admin/PublishButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAgC,MAAM,OAAO,CAAA;AAYpD,MAAM,WAAW,6BAA6B;IAC5C,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAE,6BAAkC,GAAG,KAAK,CAAC,SAAS,CAuIxF"}
1
+ {"version":3,"file":"PublishButton.d.ts","sourceRoot":"","sources":["../../src/admin/PublishButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAgC,MAAM,OAAO,CAAA;AAYpD,MAAM,WAAW,6BAA6B;IAC5C,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAE,6BAAkC,GAAG,KAAK,CAAC,SAAS,CA4IxF"}
@@ -33,9 +33,14 @@ export function PublishButton(props = {}) {
33
33
  return;
34
34
  setPublishing(true);
35
35
  try {
36
- // Persist pending edits first. Draft writes never touch `_status`, so
37
- // the trust boundary lets them through; the pipeline then evaluates
38
- // what was actually saved rather than what is on screen.
36
+ // Persist pending edits first, as a draft. Payload writes those to the
37
+ // versions table and leaves the published document alone, so the trust
38
+ // boundary lets them through; the pipeline then evaluates what was
39
+ // actually saved rather than what is on screen.
40
+ //
41
+ // `?draft=true` is what makes this a draft write. The `_status`
42
+ // override only pins the intent when form state carries a `_status` of
43
+ // its own, and mirrors what Payload's native Save Draft sends.
39
44
  if (modified) {
40
45
  const saved = await submit({
41
46
  action: `${serverURL}${api}/${collectionSlug}/${id}?draft=true&depth=0`,
@@ -1 +1 @@
1
- {"version":3,"file":"PublishButton.js","sourceRoot":"","sources":["../../src/admin/PublishButton.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PublishButton.js","sourceRoot":"","sources":["../../src/admin/PublishButton.tsx"],"names":[],"mappings":"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"}
@@ -1,13 +1,22 @@
1
1
  import type { CollectionBeforeChangeHook } from 'payload';
2
2
  /**
3
3
  * The trust boundary. This `beforeChange` hook rejects every update that
4
- * touches `_status` unless the request explicitly carries the
5
- * `bypassPublishingServer` context flag (set by the pipeline's `executeStep`).
4
+ * changes the live document's `_status` unless the request explicitly
5
+ * carries the `bypassPublishingServer` context flag (set by the pipeline's
6
+ * `executeStep`).
6
7
  *
7
8
  * Without this hook, the Payload MCP could let Claude flip a document to
8
9
  * `published` directly, sidestepping every check the publishing server
9
10
  * exists to enforce. With it, the only sanctioned path is the pipeline.
10
11
  *
12
+ * Draft writes pass through. A `draft: true` update writes a new row in the
13
+ * versions table and leaves the published document alone, so it changes no
14
+ * live status — but Payload injects `data._status = 'draft'` into every such
15
+ * update before this hook runs, which made saving a draft of a published
16
+ * document indistinguishable from unpublishing it. `createRecordDraftWritesHook`
17
+ * captures the operation's real `draft` flag so the two can be told apart;
18
+ * both hooks must be installed together.
19
+ *
11
20
  * Throws `APIError` rather than `Error` so Payload returns 400 with the
12
21
  * message intact instead of swallowing it into a 500 and a generic
13
22
  * "Something went wrong" toast.
@@ -1 +1 @@
1
- {"version":3,"file":"block-status-writes.d.ts","sourceRoot":"","sources":["../../src/hooks/block-status-writes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAEzD;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,IAAI,0BAA0B,CAsBxE"}
1
+ {"version":3,"file":"block-status-writes.d.ts","sourceRoot":"","sources":["../../src/hooks/block-status-writes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAGzD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,2BAA2B,IAAI,0BAA0B,CAoCxE"}
@@ -1,19 +1,29 @@
1
1
  import { APIError } from 'payload';
2
+ import { isDraftWrite } from './draft-writes.js';
2
3
  /**
3
4
  * The trust boundary. This `beforeChange` hook rejects every update that
4
- * touches `_status` unless the request explicitly carries the
5
- * `bypassPublishingServer` context flag (set by the pipeline's `executeStep`).
5
+ * changes the live document's `_status` unless the request explicitly
6
+ * carries the `bypassPublishingServer` context flag (set by the pipeline's
7
+ * `executeStep`).
6
8
  *
7
9
  * Without this hook, the Payload MCP could let Claude flip a document to
8
10
  * `published` directly, sidestepping every check the publishing server
9
11
  * exists to enforce. With it, the only sanctioned path is the pipeline.
10
12
  *
13
+ * Draft writes pass through. A `draft: true` update writes a new row in the
14
+ * versions table and leaves the published document alone, so it changes no
15
+ * live status — but Payload injects `data._status = 'draft'` into every such
16
+ * update before this hook runs, which made saving a draft of a published
17
+ * document indistinguishable from unpublishing it. `createRecordDraftWritesHook`
18
+ * captures the operation's real `draft` flag so the two can be told apart;
19
+ * both hooks must be installed together.
20
+ *
11
21
  * Throws `APIError` rather than `Error` so Payload returns 400 with the
12
22
  * message intact instead of swallowing it into a 500 and a generic
13
23
  * "Something went wrong" toast.
14
24
  */
15
25
  export function createBlockStatusWritesHook() {
16
- return ({ data, originalDoc, operation, context, req }) => {
26
+ return ({ collection, data, originalDoc, operation, context, req }) => {
17
27
  if (operation !== 'update')
18
28
  return data;
19
29
  if (!hasStatusChange(data))
@@ -27,6 +37,17 @@ export function createBlockStatusWritesHook() {
27
37
  }
28
38
  if (isBypassed(context) || isBypassed(req?.context))
29
39
  return data;
40
+ // A draft save touches a version, not the live document.
41
+ //
42
+ // Mirror Payload's own `isSavingDraft`, which requires the incoming
43
+ // status to be something other than `published`. A request that asks for
44
+ // `draft: true` while setting `_status: 'published'` is a real publish —
45
+ // Payload treats it as one — so it stays blocked. Without this, `draft`
46
+ // would be a way to publish around the pipeline.
47
+ if (data['_status'] !== 'published' &&
48
+ isDraftWrite(req, collection?.slug, originalDoc?.id)) {
49
+ return data;
50
+ }
30
51
  throw new APIError('Direct writes to `_status` are not allowed. Use the publishing server (publish / unpublish / rollback) so the policy pipeline runs.', 400);
31
52
  };
32
53
  }
@@ -1 +1 @@
1
- {"version":3,"file":"block-status-writes.js","sourceRoot":"","sources":["../../src/hooks/block-status-writes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGlC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE;QACxD,IAAI,SAAS,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAA;QACvC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;QAEvC,+DAA+D;QAC/D,IACE,WAAW;YACX,OAAO,WAAW,KAAK,QAAQ;YAC9B,IAAgC,CAAC,SAAS,CAAC;gBACzC,WAAuC,CAAC,SAAS,CAAC,EACrD,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;YAAE,OAAO,IAAI,CAAA;QAEhE,MAAM,IAAI,QAAQ,CAChB,qIAAqI,EACrI,GAAG,CACJ,CAAA;IACH,CAAC,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,IAAa;IACpC,OAAO,CACL,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,SAAS,IAAI,IAAI,CAC/D,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,OAAgB;IAClC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IACzD,OAAQ,OAAmC,CAAC,wBAAwB,CAAC,KAAK,IAAI,CAAA;AAChF,CAAC"}
1
+ {"version":3,"file":"block-status-writes.js","sourceRoot":"","sources":["../../src/hooks/block-status-writes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAElC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE;QACpE,IAAI,SAAS,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAA;QACvC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;QAEvC,+DAA+D;QAC/D,IACE,WAAW;YACX,OAAO,WAAW,KAAK,QAAQ;YAC9B,IAAgC,CAAC,SAAS,CAAC;gBACzC,WAAuC,CAAC,SAAS,CAAC,EACrD,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;YAAE,OAAO,IAAI,CAAA;QAEhE,yDAAyD;QACzD,EAAE;QACF,oEAAoE;QACpE,yEAAyE;QACzE,yEAAyE;QACzE,wEAAwE;QACxE,iDAAiD;QACjD,IACG,IAAgC,CAAC,SAAS,CAAC,KAAK,WAAW;YAC5D,YAAY,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAG,WAA4C,EAAE,EAAE,CAAC,EACtF,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QAED,MAAM,IAAI,QAAQ,CAChB,qIAAqI,EACrI,GAAG,CACJ,CAAA;IACH,CAAC,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,IAAa;IACpC,OAAO,CACL,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,SAAS,IAAI,IAAI,CAC/D,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,OAAgB;IAClC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IACzD,OAAQ,OAAmC,CAAC,wBAAwB,CAAC,KAAK,IAAI,CAAA;AAChF,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { CollectionBeforeOperationHook, PayloadRequest } from 'payload';
2
+ /**
3
+ * Records whether the update in flight is a draft write, so the
4
+ * status-write hook can tell a draft save apart from an unpublish.
5
+ *
6
+ * It has to be recorded here because `beforeChange` cannot work it out:
7
+ * Payload sets `data._status = 'draft'` for any `draft: true` update
8
+ * *before* calling the hook, whether or not the caller supplied it —
9
+ *
10
+ * const isSavingDraft = Boolean(draftArg && hasDraftsEnabled(config))
11
+ * && data._status !== 'published' && !publishAllLocales
12
+ * if (isSavingDraft) { data._status = 'draft' }
13
+ *
14
+ * so by the time `beforeChange` runs, saving a draft of a published
15
+ * document and unpublishing it look identical: `data._status` is `'draft'`
16
+ * and `originalDoc._status` is `'published'` in both cases.
17
+ *
18
+ * `beforeOperation` is the one place that sees the operation's own `draft`
19
+ * argument, and it sees it identically on the Local API, REST and GraphQL —
20
+ * unlike `req.query.draft`, which is only populated on the REST path.
21
+ * `beforeOperation` shares `req.context` with `beforeChange`, which is how
22
+ * the flag gets across.
23
+ */
24
+ export declare function createRecordDraftWritesHook(): CollectionBeforeOperationHook;
25
+ /**
26
+ * Whether the update in flight on this document is a draft write.
27
+ *
28
+ * Defaults to `false` when nothing was recorded, so a caller that installs
29
+ * the status-write hook without this one keeps the stricter behaviour.
30
+ */
31
+ export declare function isDraftWrite(req: Pick<PayloadRequest, 'context'> | undefined, collectionSlug: string | undefined, id: unknown): boolean;
32
+ //# sourceMappingURL=draft-writes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft-writes.d.ts","sourceRoot":"","sources":["../../src/hooks/draft-writes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAM5E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,2BAA2B,IAAI,6BAA6B,CAW3E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,GAAG,SAAS,EAChD,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,EAAE,EAAE,OAAO,GACV,OAAO,CAcT"}
@@ -0,0 +1,76 @@
1
+ const DRAFT_WRITES_KEY = '__throughlinePublishingDraftWrites';
2
+ /**
3
+ * Records whether the update in flight is a draft write, so the
4
+ * status-write hook can tell a draft save apart from an unpublish.
5
+ *
6
+ * It has to be recorded here because `beforeChange` cannot work it out:
7
+ * Payload sets `data._status = 'draft'` for any `draft: true` update
8
+ * *before* calling the hook, whether or not the caller supplied it —
9
+ *
10
+ * const isSavingDraft = Boolean(draftArg && hasDraftsEnabled(config))
11
+ * && data._status !== 'published' && !publishAllLocales
12
+ * if (isSavingDraft) { data._status = 'draft' }
13
+ *
14
+ * so by the time `beforeChange` runs, saving a draft of a published
15
+ * document and unpublishing it look identical: `data._status` is `'draft'`
16
+ * and `originalDoc._status` is `'published'` in both cases.
17
+ *
18
+ * `beforeOperation` is the one place that sees the operation's own `draft`
19
+ * argument, and it sees it identically on the Local API, REST and GraphQL —
20
+ * unlike `req.query.draft`, which is only populated on the REST path.
21
+ * `beforeOperation` shares `req.context` with `beforeChange`, which is how
22
+ * the flag gets across.
23
+ */
24
+ export function createRecordDraftWritesHook() {
25
+ return ({ args, operation, req }) => {
26
+ // `update` and `updateByID` both arrive as the `update` hook operation.
27
+ if (operation !== 'update')
28
+ return;
29
+ const updateArgs = args;
30
+ const slug = collectionSlug(args);
31
+ if (!slug)
32
+ return;
33
+ registry(req)[draftWriteKey(slug, updateArgs.id)] = updateArgs.draft === true;
34
+ };
35
+ }
36
+ /**
37
+ * Whether the update in flight on this document is a draft write.
38
+ *
39
+ * Defaults to `false` when nothing was recorded, so a caller that installs
40
+ * the status-write hook without this one keeps the stricter behaviour.
41
+ */
42
+ export function isDraftWrite(req, collectionSlug, id) {
43
+ if (!req || !collectionSlug)
44
+ return false;
45
+ const entries = req.context?.[DRAFT_WRITES_KEY];
46
+ if (!entries)
47
+ return false;
48
+ // Keyed per document so a nested write to a different document during the
49
+ // same request cannot be mistaken for this one.
50
+ const scoped = entries[draftWriteKey(collectionSlug, id)];
51
+ if (scoped !== undefined)
52
+ return scoped;
53
+ // Bulk updates match by `where` and carry no id.
54
+ return entries[draftWriteKey(collectionSlug, undefined)] === true;
55
+ }
56
+ function draftWriteKey(collectionSlug, id) {
57
+ return `${collectionSlug}:${id === undefined || id === null ? '*' : String(id)}`;
58
+ }
59
+ function collectionSlug(args) {
60
+ const slug = args?.collection?.config
61
+ ?.slug;
62
+ return typeof slug === 'string' ? slug : undefined;
63
+ }
64
+ function registry(req) {
65
+ // Payload always assigns `req.context`, but attach it if absent rather
66
+ // than writing the flag to an object nothing else can see.
67
+ if (!req.context) {
68
+ req.context = {};
69
+ }
70
+ const context = req.context;
71
+ if (!context[DRAFT_WRITES_KEY]) {
72
+ context[DRAFT_WRITES_KEY] = {};
73
+ }
74
+ return context[DRAFT_WRITES_KEY];
75
+ }
76
+ //# sourceMappingURL=draft-writes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft-writes.js","sourceRoot":"","sources":["../../src/hooks/draft-writes.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG,oCAAoC,CAAA;AAI7D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,EAAE;QAClC,wEAAwE;QACxE,IAAI,SAAS,KAAK,QAAQ;YAAE,OAAM;QAElC,MAAM,UAAU,GAAG,IAAiD,CAAA;QACpE,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,CAAC,IAAI;YAAE,OAAM;QAEjB,QAAQ,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,KAAK,IAAI,CAAA;IAC/E,CAAC,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,GAAgD,EAChD,cAAkC,EAClC,EAAW;IAEX,IAAI,CAAC,GAAG,IAAI,CAAC,cAAc;QAAE,OAAO,KAAK,CAAA;IACzC,MAAM,OAAO,GAAI,GAAG,CAAC,OAA+C,EAAE,CACpE,gBAAgB,CACiB,CAAA;IACnC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAE1B,0EAA0E;IAC1E,gDAAgD;IAChD,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAA;IACzD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAA;IAEvC,iDAAiD;IACjD,OAAO,OAAO,CAAC,aAAa,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI,CAAA;AACnE,CAAC;AAED,SAAS,aAAa,CAAC,cAAsB,EAAE,EAAW;IACxD,OAAO,GAAG,cAAc,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAA;AAClF,CAAC;AAED,SAAS,cAAc,CAAC,IAAa;IACnC,MAAM,IAAI,GAAI,IAAyD,EAAE,UAAU,EAAE,MAAM;QACzF,EAAE,IAAI,CAAA;IACR,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;AACpD,CAAC;AAED,SAAS,QAAQ,CAAC,GAAmB;IACnC,uEAAuE;IACvE,2DAA2D;IAC3D,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACjB,GAAG,CAAC,OAAO,GAAG,EAA+B,CAAA;IAC/C,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,OAA6C,CAAA;IACjE,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,gBAAgB,CAAC,GAAG,EAA+B,CAAA;IAC7D,CAAC;IACD,OAAO,OAAO,CAAC,gBAAgB,CAAuB,CAAA;AACxD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAA;AAQvE,OAAO,EACL,KAAK,uBAAuB,EAG7B,MAAM,cAAc,CAAA;AAoBrB,eAAO,MAAM,gBAAgB,EAAE,UAAU,CAAC,uBAAuB,CAuG9D,CAAA"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAA;AAQvE,OAAO,EACL,KAAK,uBAAuB,EAG7B,MAAM,cAAc,CAAA;AAqBrB,eAAO,MAAM,gBAAgB,EAAE,UAAU,CAAC,uBAAuB,CA8G9D,CAAA"}
package/dist/plugin.js CHANGED
@@ -2,6 +2,7 @@ import { getPluginRegistry } from '@forumone/throughline-plugin-contract';
2
2
  import { createMcpHandler, createNamedLogger, defaultLogger, getAuditWriter, } from '@forumone/throughline-core';
3
3
  import { resolveCollection, validateOptions, } from './options.js';
4
4
  import { createBlockStatusWritesHook } from './hooks/block-status-writes.js';
5
+ import { createRecordDraftWritesHook } from './hooks/draft-writes.js';
5
6
  import { createAdminEndpoints } from './endpoints/admin.js';
6
7
  import { attachPublishingService, createPublishingService } from './service.js';
7
8
  import { createGetPublishStatusTool, createPublishTool, createRollbackTool, createSchedulePublishTool, createUnpublishTool, } from './tools/index.js';
@@ -24,9 +25,16 @@ export const publishingPlugin = (rawOptions) => (incomingConfig) => {
24
25
  return collection;
25
26
  return {
26
27
  ...collection,
27
- // The trust boundary: nothing may write `_status` outside the pipeline.
28
+ // The trust boundary: nothing may change the live document's
29
+ // `_status` outside the pipeline. `beforeOperation` records whether
30
+ // the update is a draft write, which is the only place Payload
31
+ // exposes that; `beforeChange` enforces. They must ship together.
28
32
  hooks: {
29
33
  ...(collection.hooks ?? {}),
34
+ beforeOperation: [
35
+ ...(collection.hooks?.beforeOperation ?? []),
36
+ createRecordDraftWritesHook(),
37
+ ],
30
38
  beforeChange: [
31
39
  ...(collection.hooks?.beforeChange ?? []),
32
40
  createBlockStatusWritesHook(),
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forumone/throughline-publishing",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Policy-gated publishing server for Throughline. Wraps Payload's update operation with composition, accessibility, required-field, embargo, and approval gating.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",