drupal-mcp-connector 2.13.0 → 2.14.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.
@@ -12,19 +12,19 @@
12
12
  *
13
13
  * Two distinct cases share that core 400:
14
14
  *
15
- * - **#166** — `rel:working-copy` resolves. PATCH (and the dryRun probe)
16
- * target `?resourceVersion=rel:working-copy`. Do not discard, do not
17
- * retry the canonical URL, and do not tell the caller to publish first.
15
+ * - **#166** — `rel:working-copy` resolves. Both preflight and write use
16
+ * Sentinel's /mcp-draft endpoint with verified live/working revision IDs.
17
+ * Core rejects resourceVersion on PATCH. Never retry the canonical URL.
18
18
  * - **#201** — the working-copy alias does not resolve, but core still
19
19
  * blocks. That is a stray revision row. Refuse with revision-surgery
20
20
  * language. `workingCopy: null` is not proof the node is writable.
21
21
  *
22
- * A working-copy 400 *after* targeting the working copy is a stale or
23
- * concurrent write — refuse, do not fall back to discard.
22
+ * Unsupported endpoints and stale revisions fail closed, without discard.
24
23
  */
25
24
 
26
25
  import { entityLooksModerated, hasExplicitModerationState } from "./moderation-default.js";
27
26
  import { entityRevisionId } from "./write-revision.js";
27
+ import { writeDraft } from "./draft-write.js";
28
28
 
29
29
  /** Stable error code for a core working-copy / not-latest-revision block. */
30
30
  export const PATCH_BLOCKED_CODE = "PATCH_BLOCKED";
@@ -59,7 +59,7 @@ export const PATCH_WORKING_COPY_STALE_MESSAGE =
59
59
 
60
60
  /**
61
61
  * Operator message for a core working-copy 400.
62
- * A resolvable working copy is edited in place (#166) — this message is only
62
+ * A resolvable working copy gets a new draft revision (#166) — this message is only
63
63
  * for the invisible-row case (#201).
64
64
  * @returns {string}
65
65
  */
@@ -300,11 +300,18 @@ export async function preflightPatchWritable({
300
300
  * @returns {Promise<{resourceVersion: ?string, workingCopy: ?object, liveVid: ?number|string, workingVid: ?number|string}>}
301
301
  */
302
302
  export async function prepareGuardedPatch(backend, {
303
- entityType, bundle, id, existing, attributes,
303
+ entityType, bundle, id, existing, attributes, relationships,
304
304
  }) {
305
305
  const target = shouldPreflightPatch({ existing, attributes })
306
306
  ? await resolveWorkingCopyPatchTarget(backend, { entityType, bundle, id, existing })
307
307
  : { resourceVersion: undefined, workingCopy: null, liveVid: null, workingVid: null };
308
+ if (target.resourceVersion) {
309
+ target.draftRevision = { liveVid: target.liveVid, workingVid: target.workingVid };
310
+ await writeDraft(backend, {
311
+ entityType, bundle, id, attributes, relationships, draftRevision: target.draftRevision,
312
+ }, true);
313
+ return target;
314
+ }
308
315
  await preflightPatchWritable({
309
316
  backend, entityType, bundle, id, existing, attributes,
310
317
  resourceVersion: target.resourceVersion,
@@ -323,6 +330,10 @@ export async function prepareGuardedPatch(backend, {
323
330
  */
324
331
  export async function updateEntityGuarded(backend, input) {
325
332
  try {
333
+ if (input?.draftRevision) return await writeDraft(backend, input);
334
+ if (input?.resourceVersion) {
335
+ throw new Error("Core JSON:API does not support revision-selected PATCH. A governed draft preflight is required.");
336
+ }
326
337
  return await backend.updateEntity(input);
327
338
  } catch (err) {
328
339
  if (!isWorkingCopyPatchError(err)) throw err;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Tenant-side local policy enforcement (#253 / DEV-125).
2
+ * Tenant-side local policy enforcement (#253).
3
3
  *
4
4
  * Loopback stand-in for mcp_sentinel `McpPolicyBundleRegistry`: mint / verify
5
5
  * / activate / simulate / revoke / rollback / emergency deny. The relay edge
@@ -1,5 +1,5 @@
1
1
  /**
2
- * W&L-operated dual-control promotion ledger (#253 / DEV-125).
2
+ * W&L-operated dual-control promotion ledger (#253).
3
3
  *
4
4
  * The edge never mints a Sentinel HMAC seal. A promotion is an already-sealed
5
5
  * portable document plus two distinct operator ids. Eligibility is the gate
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Relay tenant agent (#232) — the DEV-294 AC4 slice, tenant side.
2
+ * Relay tenant agent (#232) — the hosted-edge slice, tenant side.
3
3
  *
4
4
  * Dials OUT to the edge's agent channel and serves the real connector server
5
5
  * (`createConnectorServerFactory`) over the framed tunnel. The agent never