ofiere-openclaw-plugin 4.56.7 → 4.56.9

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/dist/src/tools.js CHANGED
@@ -1038,12 +1038,15 @@ async function handleUpdateTask(supabase, userId, params) {
1038
1038
  updates.subagent_id = subCheck.subagentId;
1039
1039
  }
1040
1040
  }
1041
- // If task is being marked DONE or FAILED, auto-complete any linked scheduler events
1041
+ // If task is being marked DONE or FAILED, auto-complete any linked scheduler events.
1042
+ // A-4 plugin parity (2026-05-18) — scope by user_id so cross-tenant task_id
1043
+ // can't trigger foreign scheduler flip via plugin tool path.
1042
1044
  if (params.status === "DONE" || params.status === "FAILED") {
1043
1045
  try {
1044
1046
  await supabase
1045
1047
  .from("scheduler_events")
1046
1048
  .update({ status: "completed", next_run_at: null, updated_at: new Date().toISOString() })
1049
+ .eq("user_id", userId)
1047
1050
  .eq("task_id", params.task_id);
1048
1051
  }
1049
1052
  catch (_schedErr) {
@@ -1143,7 +1146,7 @@ async function handleDeleteTask(supabase, userId, params) {
1143
1146
  if (!params.task_id)
1144
1147
  return err("Missing required field: task_id");
1145
1148
  const taskId = params.task_id;
1146
- await supabase.from("scheduler_events").delete().eq("task_id", taskId);
1149
+ await supabase.from("scheduler_events").delete().eq("task_id", taskId).eq("user_id", userId);
1147
1150
  const { data: subtasks } = await supabase
1148
1151
  .from("tasks")
1149
1152
  .select("id")
@@ -1151,7 +1154,7 @@ async function handleDeleteTask(supabase, userId, params) {
1151
1154
  .eq("user_id", userId);
1152
1155
  if (subtasks && subtasks.length > 0) {
1153
1156
  for (const sub of subtasks) {
1154
- await supabase.from("scheduler_events").delete().eq("task_id", sub.id);
1157
+ await supabase.from("scheduler_events").delete().eq("task_id", sub.id).eq("user_id", userId);
1155
1158
  }
1156
1159
  await supabase
1157
1160
  .from("tasks")
@@ -1838,7 +1841,7 @@ function registerScheduleOps(api, supabase, userId) {
1838
1841
  if (upd.status === "completed" || upd.status === "cancelled") {
1839
1842
  upd.next_run_at = null;
1840
1843
  }
1841
- const { error } = await supabase.from("scheduler_events").update(upd).eq("id", params.id);
1844
+ const { error } = await supabase.from("scheduler_events").update(upd).eq("id", params.id).eq("user_id", userId);
1842
1845
  if (error)
1843
1846
  return err(error.message);
1844
1847
  return ok({ message: "Event updated", ok: true });
@@ -1846,7 +1849,7 @@ function registerScheduleOps(api, supabase, userId) {
1846
1849
  case "delete": {
1847
1850
  if (!params.id)
1848
1851
  return err("Missing required: id");
1849
- const { error } = await supabase.from("scheduler_events").delete().eq("id", params.id);
1852
+ const { error } = await supabase.from("scheduler_events").delete().eq("id", params.id).eq("user_id", userId);
1850
1853
  if (error)
1851
1854
  return err(error.message);
1852
1855
  return ok({ message: "Event deleted", ok: true });
@@ -1960,7 +1963,7 @@ function registerKnowledgeOps(api, supabase, userId) {
1960
1963
  upd[k] = params[k];
1961
1964
  if (Object.keys(upd).length === 0)
1962
1965
  return err("No valid fields to update");
1963
- const { error } = await supabase.from("knowledge_documents").update(upd).eq("id", params.id);
1966
+ const { error } = await supabase.from("knowledge_documents").update(upd).eq("id", params.id).eq("user_id", userId);
1964
1967
  if (error)
1965
1968
  return err(error.message);
1966
1969
  return ok({ message: "Document updated", ok: true });
@@ -1968,7 +1971,7 @@ function registerKnowledgeOps(api, supabase, userId) {
1968
1971
  case "delete": {
1969
1972
  if (!params.id)
1970
1973
  return err("Missing required: id");
1971
- const { error } = await supabase.from("knowledge_documents").delete().eq("id", params.id);
1974
+ const { error } = await supabase.from("knowledge_documents").delete().eq("id", params.id).eq("user_id", userId);
1972
1975
  if (error)
1973
1976
  return err(error.message);
1974
1977
  return ok({ message: "Document deleted", ok: true });
@@ -2313,7 +2316,9 @@ function registerWorkflowOps(api, supabase, userId) {
2313
2316
  const wfId = (params.id || params.workflow_id);
2314
2317
  if (!wfId)
2315
2318
  return err("Missing required: id");
2316
- await supabase.from("workflow_runs").delete().eq("workflow_id", wfId);
2319
+ // A-4 plugin parity (2026-05-18) — scope cascade so cross-tenant
2320
+ // workflow_id can't trigger foreign workflow_runs wipe via plugin.
2321
+ await supabase.from("workflow_runs").delete().eq("user_id", userId).eq("workflow_id", wfId);
2317
2322
  const { error } = await supabase.from("workflows").delete().eq("id", wfId).eq("user_id", userId);
2318
2323
  if (error)
2319
2324
  return err(error.message);
@@ -2670,13 +2675,13 @@ function registerNotifyOps(api, supabase, userId, resolveAgent) {
2670
2675
  case "mark_read": {
2671
2676
  if (!params.id)
2672
2677
  return err("Missing required: id");
2673
- const { error } = await supabase.from("notifications").update({ read: true }).eq("id", params.id);
2678
+ const { error } = await supabase.from("notifications").update({ read: true }).eq("id", params.id).eq("user_id", userId);
2674
2679
  if (error)
2675
2680
  return err(error.message);
2676
2681
  return ok({ message: "Notification marked as read", ok: true });
2677
2682
  }
2678
2683
  case "mark_all_read": {
2679
- const { error } = await supabase.from("notifications").update({ read: true }).eq("read", false);
2684
+ const { error } = await supabase.from("notifications").update({ read: true }).eq("read", false).eq("user_id", userId);
2680
2685
  if (error)
2681
2686
  return err(error.message);
2682
2687
  return ok({ message: "All notifications marked as read", ok: true });
@@ -2684,7 +2689,7 @@ function registerNotifyOps(api, supabase, userId, resolveAgent) {
2684
2689
  case "delete": {
2685
2690
  if (!params.id)
2686
2691
  return err("Missing required: id");
2687
- const { error } = await supabase.from("notifications").delete().eq("id", params.id);
2692
+ const { error } = await supabase.from("notifications").delete().eq("id", params.id).eq("user_id", userId);
2688
2693
  if (error)
2689
2694
  return err(error.message);
2690
2695
  return ok({ message: "Notification deleted", ok: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ofiere-openclaw-plugin",
3
- "version": "4.56.7",
3
+ "version": "4.56.9",
4
4
  "type": "module",
5
5
  "description": "OpenClaw plugin for Ofiere PM - 18 meta-tools covering tasks, agents, projects, scheduling, knowledge, workflows, notifications, memory, prompts, constellation, space file management, execution plan builder, SOP management, agent brain, talent management, corporate frameworks, agent office canvas, and PM gate approvals",
6
6
  "keywords": [
package/src/tools.ts CHANGED
@@ -1147,12 +1147,15 @@ async function handleUpdateTask(
1147
1147
  }
1148
1148
  }
1149
1149
 
1150
- // If task is being marked DONE or FAILED, auto-complete any linked scheduler events
1150
+ // If task is being marked DONE or FAILED, auto-complete any linked scheduler events.
1151
+ // A-4 plugin parity (2026-05-18) — scope by user_id so cross-tenant task_id
1152
+ // can't trigger foreign scheduler flip via plugin tool path.
1151
1153
  if (params.status === "DONE" || params.status === "FAILED") {
1152
1154
  try {
1153
1155
  await supabase
1154
1156
  .from("scheduler_events")
1155
1157
  .update({ status: "completed", next_run_at: null, updated_at: new Date().toISOString() })
1158
+ .eq("user_id", userId)
1156
1159
  .eq("task_id", params.task_id as string);
1157
1160
  } catch (_schedErr) {
1158
1161
  // Non-fatal: task update should still proceed
@@ -1264,7 +1267,7 @@ async function handleDeleteTask(
1264
1267
  if (!params.task_id) return err("Missing required field: task_id");
1265
1268
  const taskId = params.task_id as string;
1266
1269
 
1267
- await supabase.from("scheduler_events").delete().eq("task_id", taskId);
1270
+ await supabase.from("scheduler_events").delete().eq("task_id", taskId).eq("user_id", userId);
1268
1271
 
1269
1272
  const { data: subtasks } = await supabase
1270
1273
  .from("tasks")
@@ -1274,7 +1277,7 @@ async function handleDeleteTask(
1274
1277
 
1275
1278
  if (subtasks && subtasks.length > 0) {
1276
1279
  for (const sub of subtasks) {
1277
- await supabase.from("scheduler_events").delete().eq("task_id", sub.id);
1280
+ await supabase.from("scheduler_events").delete().eq("task_id", sub.id).eq("user_id", userId);
1278
1281
  }
1279
1282
  await supabase
1280
1283
  .from("tasks")
@@ -1990,13 +1993,13 @@ function registerScheduleOps(
1990
1993
  if (upd.status === "completed" || upd.status === "cancelled") {
1991
1994
  upd.next_run_at = null;
1992
1995
  }
1993
- const { error } = await supabase.from("scheduler_events").update(upd).eq("id", params.id);
1996
+ const { error } = await supabase.from("scheduler_events").update(upd).eq("id", params.id).eq("user_id", userId);
1994
1997
  if (error) return err(error.message);
1995
1998
  return ok({ message: "Event updated", ok: true });
1996
1999
  }
1997
2000
  case "delete": {
1998
2001
  if (!params.id) return err("Missing required: id");
1999
- const { error } = await supabase.from("scheduler_events").delete().eq("id", params.id);
2002
+ const { error } = await supabase.from("scheduler_events").delete().eq("id", params.id).eq("user_id", userId);
2000
2003
  if (error) return err(error.message);
2001
2004
  return ok({ message: "Event deleted", ok: true });
2002
2005
  }
@@ -2107,13 +2110,13 @@ function registerKnowledgeOps(
2107
2110
  const upd: Record<string, any> = {};
2108
2111
  for (const k of allowed) if ((params as any)[k] !== undefined) upd[k] = (params as any)[k];
2109
2112
  if (Object.keys(upd).length === 0) return err("No valid fields to update");
2110
- const { error } = await supabase.from("knowledge_documents").update(upd).eq("id", params.id);
2113
+ const { error } = await supabase.from("knowledge_documents").update(upd).eq("id", params.id).eq("user_id", userId);
2111
2114
  if (error) return err(error.message);
2112
2115
  return ok({ message: "Document updated", ok: true });
2113
2116
  }
2114
2117
  case "delete": {
2115
2118
  if (!params.id) return err("Missing required: id");
2116
- const { error } = await supabase.from("knowledge_documents").delete().eq("id", params.id);
2119
+ const { error } = await supabase.from("knowledge_documents").delete().eq("id", params.id).eq("user_id", userId);
2117
2120
  if (error) return err(error.message);
2118
2121
  return ok({ message: "Document deleted", ok: true });
2119
2122
  }
@@ -2464,7 +2467,9 @@ function registerWorkflowOps(
2464
2467
  case "delete": {
2465
2468
  const wfId = (params.id || params.workflow_id) as string;
2466
2469
  if (!wfId) return err("Missing required: id");
2467
- await supabase.from("workflow_runs").delete().eq("workflow_id", wfId);
2470
+ // A-4 plugin parity (2026-05-18) — scope cascade so cross-tenant
2471
+ // workflow_id can't trigger foreign workflow_runs wipe via plugin.
2472
+ await supabase.from("workflow_runs").delete().eq("user_id", userId).eq("workflow_id", wfId);
2468
2473
  const { error } = await supabase.from("workflows").delete().eq("id", wfId).eq("user_id", userId);
2469
2474
  if (error) return err(error.message);
2470
2475
  return ok({ message: "Workflow and associated runs deleted", ok: true });
@@ -2840,18 +2845,18 @@ function registerNotifyOps(
2840
2845
  }
2841
2846
  case "mark_read": {
2842
2847
  if (!params.id) return err("Missing required: id");
2843
- const { error } = await supabase.from("notifications").update({ read: true }).eq("id", params.id);
2848
+ const { error } = await supabase.from("notifications").update({ read: true }).eq("id", params.id).eq("user_id", userId);
2844
2849
  if (error) return err(error.message);
2845
2850
  return ok({ message: "Notification marked as read", ok: true });
2846
2851
  }
2847
2852
  case "mark_all_read": {
2848
- const { error } = await supabase.from("notifications").update({ read: true }).eq("read", false);
2853
+ const { error } = await supabase.from("notifications").update({ read: true }).eq("read", false).eq("user_id", userId);
2849
2854
  if (error) return err(error.message);
2850
2855
  return ok({ message: "All notifications marked as read", ok: true });
2851
2856
  }
2852
2857
  case "delete": {
2853
2858
  if (!params.id) return err("Missing required: id");
2854
- const { error } = await supabase.from("notifications").delete().eq("id", params.id);
2859
+ const { error } = await supabase.from("notifications").delete().eq("id", params.id).eq("user_id", userId);
2855
2860
  if (error) return err(error.message);
2856
2861
  return ok({ message: "Notification deleted", ok: true });
2857
2862
  }