@ai-matrx/associations 0.9.32 → 0.10.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.
@@ -622,6 +622,7 @@ var ENTITY_TYPE_METADATA = {
622
622
  "mandate": { token: "mandate", schema: "mandate", table: "definition", label: "Mandate Definition (new)", baseTier: 1, isComponent: false, isModule: false, isListed: true, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
623
623
  "mandate_advance_batch_row": { token: "mandate_advance_batch_row", schema: "mandate", table: "advance_batch_row", label: "Pin advance batch row", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
624
624
  "mandate_binding": { token: "mandate_binding", schema: "mandate", table: "binding", label: "Mandate Binding (new)", baseTier: 1, isComponent: false, isModule: false, isListed: true, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
625
+ "mandate_goal_clauses": { token: "mandate_goal_clauses", schema: "mandate", table: "goal_clauses", label: "Mandate Goal Clauses", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
625
626
  "mandate_observation": { token: "mandate_observation", schema: "mandate", table: "observation", label: "Mandate Observation", baseTier: 1, isComponent: true, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
626
627
  "mandate_reference": { token: "mandate_reference", schema: "mandate", table: "reference", label: "Mandate Reference", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
627
628
  "mandate_scan": { token: "mandate_scan", schema: "mandate", table: "scan", label: "Mandate Scan", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
@@ -668,6 +669,7 @@ var ENTITY_TYPE_METADATA = {
668
669
  "notification_event_override": { token: "notification_event_override", schema: "communication", table: "notification_event_override", label: "Notification Event Override", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
669
670
  "notification_event_type": { token: "notification_event_type", schema: "communication", table: "notification_event_type", label: "Notification Event Type", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
670
671
  "notification_preference": { token: "notification_preference", schema: "communication", table: "notification_preference", label: "Notification Preference", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
672
+ "notification_submission": { token: "notification_submission", schema: "communication", table: "notification_submission", label: "Self notification submission", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
671
673
  "notify_outsider_door_baseline": { token: "notify_outsider_door_baseline", schema: "hr", table: "notify_outsider_door_baseline", label: "Notify Outsider Door Baseline", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
672
674
  "oauth_handoff_claim": { token: "oauth_handoff_claim", schema: "platform", table: "_oauth_handoff_claim", label: "Oauth Handoff Claim", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
673
675
  "opinion_clusters": { token: "opinion_clusters", schema: "legal", table: "opinion_clusters", label: "Opinion Clusters", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
@@ -716,6 +718,7 @@ var ENTITY_TYPE_METADATA = {
716
718
  "plan_node_artifact": { token: "plan_node_artifact", schema: "plan", table: "node_artifact", label: "Plan Node Artifact", baseTier: 1, isComponent: true, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
717
719
  "plan_node_step": { token: "plan_node_step", schema: "plan", table: "node_step", label: "Plan Node Step", baseTier: 1, isComponent: true, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
718
720
  "plan_profile": { token: "plan_profile", schema: "plan", table: "profile", label: "Plan Vertical Profile", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: "vertical", contentRole: null, referenceCategory: null },
721
+ "platform_action_request": { token: "platform_action_request", schema: "platform", table: "action_request", label: "Action Request", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
719
722
  "platform_actor_session": { token: "platform_actor_session", schema: "platform", table: "actor_session", label: "Actor session", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
720
723
  "platform_actor_token": { token: "platform_actor_token", schema: "platform", table: "actor_token", label: "Actor token", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
721
724
  "platform_actor_token_event": { token: "platform_actor_token_event", schema: "platform", table: "actor_token_event", label: "Actor token event", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
@@ -1612,6 +1615,7 @@ var ENTITY_TYPE_TOKENS = [
1612
1615
  "mandate",
1613
1616
  "mandate_advance_batch_row",
1614
1617
  "mandate_binding",
1618
+ "mandate_goal_clauses",
1615
1619
  "mandate_observation",
1616
1620
  "mandate_reference",
1617
1621
  "mandate_scan",
@@ -1658,6 +1662,7 @@ var ENTITY_TYPE_TOKENS = [
1658
1662
  "notification_event_override",
1659
1663
  "notification_event_type",
1660
1664
  "notification_preference",
1665
+ "notification_submission",
1661
1666
  "notify_outsider_door_baseline",
1662
1667
  "oauth_handoff_claim",
1663
1668
  "opinion_clusters",
@@ -1706,6 +1711,7 @@ var ENTITY_TYPE_TOKENS = [
1706
1711
  "plan_node_artifact",
1707
1712
  "plan_node_step",
1708
1713
  "plan_profile",
1714
+ "platform_action_request",
1709
1715
  "platform_actor_session",
1710
1716
  "platform_actor_token",
1711
1717
  "platform_actor_token_event",
@@ -3189,31 +3195,7 @@ function createTitlesService(deps, candidates) {
3189
3195
 
3190
3196
  // src/core/entityRows.ts
3191
3197
  function createEntityRowsService(deps, titles) {
3192
- const { dataSource, identity, registry, errorSink } = deps;
3193
- function tableFor(token, schema, table) {
3194
- if (schema && schema !== "public") {
3195
- if (!dataSource.schema) {
3196
- const error = `dataSource has no schema() capability \u2014 entity-row writes for "${token}" (${schema}.${table}) need a table-capable dataSource (a real supabase-js client)`;
3197
- errorSink({
3198
- code: "datasource_missing_table_capability",
3199
- message: `[entityRows] ${error}`,
3200
- context: { token, schema, table }
3201
- });
3202
- return { ok: false, error };
3203
- }
3204
- return { ok: true, query: dataSource.schema(schema).from(table) };
3205
- }
3206
- if (!dataSource.from) {
3207
- const error = `dataSource has no from() capability \u2014 entity-row writes for "${token}" need a table-capable dataSource (a real supabase-js client)`;
3208
- errorSink({
3209
- code: "datasource_missing_table_capability",
3210
- message: `[entityRows] ${error}`,
3211
- context: { token, schema, table }
3212
- });
3213
- return { ok: false, error };
3214
- }
3215
- return { ok: true, query: dataSource.from(table) };
3216
- }
3198
+ const { dataSource, registry, errorSink } = deps;
3217
3199
  function requireTitleColumn(token, op) {
3218
3200
  const info = registry.getEntityInfo(token);
3219
3201
  if (!info.titleColumn) {
@@ -3225,43 +3207,68 @@ function createEntityRowsService(deps, titles) {
3225
3207
  });
3226
3208
  return { ok: false, error };
3227
3209
  }
3228
- return { ok: true, titleColumn: info.titleColumn };
3210
+ return { ok: true };
3229
3211
  }
3230
3212
  return {
3231
3213
  /**
3232
- * Insert one row of `token`'s backing table named `title`, owned by the
3233
- * current user (when the table has an owner column). Returns the new
3234
- * row's id + title. The caller wires associations afterwards — this
3235
- * layer never writes edges.
3214
+ * Create one row of `token`'s backing table named `title`, through
3215
+ * `public.entity_row_create`. The door stamps `created_by` from `auth.uid()`,
3216
+ * checks the caller can act in the organization, and refuses machinery tokens and
3217
+ * tables with no organization by name. Returns the new row's id + title. The
3218
+ * caller wires associations afterwards — this layer never writes edges.
3236
3219
  */
3237
3220
  async createEntityRow(token, args) {
3238
3221
  const gate = requireTitleColumn(token, "creating rows");
3239
3222
  if (!gate.ok) return gate;
3240
- const info = registry.getEntityInfo(token);
3241
3223
  const title = args.title.trim();
3242
3224
  if (!title) return { ok: false, error: "Name is required" };
3225
+ const extras = Object.keys(args.extraColumns ?? {});
3226
+ if (extras.length > 0) {
3227
+ const error = `A new ${registry.getEntityInfo(token).label} cannot be created here with ${extras.join(", ")}: the shared create door writes the name, the owner and the organization and nothing else. Create it with this feature's own create service, then attach it.`;
3228
+ errorSink({
3229
+ code: "entity_row_extra_columns_unsupported",
3230
+ message: `[createEntityRow] extraColumns are not writable through entity_row_create for "${token}": ${extras.join(", ")}`,
3231
+ context: { token, extras }
3232
+ });
3233
+ return { ok: false, error };
3234
+ }
3235
+ if (!args.orgId) {
3236
+ const error = `Name the organization this ${registry.getEntityInfo(token).label} belongs to.`;
3237
+ errorSink({
3238
+ code: "entity_row_missing_organization",
3239
+ message: `[createEntityRow] no organization supplied for "${token}"; entity_row_create requires one`,
3240
+ context: { token }
3241
+ });
3242
+ return { ok: false, error };
3243
+ }
3243
3244
  try {
3244
- const userId = identity.requireUserId();
3245
- const table = tableFor(token, info.schema, info.table);
3246
- if (!table.ok) return table;
3247
- const row = {
3248
- [gate.titleColumn]: title,
3249
- ...info.ownerColumn ? { [info.ownerColumn]: userId } : {},
3250
- ...info.orgColumn && args.orgId ? { [info.orgColumn]: args.orgId } : {},
3251
- ...args.extraColumns ?? {}
3252
- };
3253
- const { data, error } = await table.query.insert(row).select("id").single();
3245
+ const { data, error } = await dataSource.rpc("entity_row_create", {
3246
+ p_token: token,
3247
+ p_title: title,
3248
+ p_organization_id: args.orgId
3249
+ });
3254
3250
  if (error) {
3255
3251
  errorSink({
3256
3252
  code: "entity_row_insert_failed",
3257
- message: `[createEntityRow] insert failed for "${token}": ${error.message}`,
3253
+ message: `[createEntityRow] entity_row_create failed for "${token}": ${error.message}`,
3258
3254
  context: { token, detail: error }
3259
3255
  });
3260
3256
  return { ok: false, error: error.message };
3261
3257
  }
3262
- const id = String(data.id);
3263
- titles.prime(token, id, title);
3264
- return { ok: true, data: { id, title } };
3258
+ const row = data;
3259
+ if (!row || typeof row.id !== "string" || !row.id) {
3260
+ const msg = "The create door returned no record.";
3261
+ errorSink({
3262
+ code: "entity_row_insert_failed",
3263
+ message: `[createEntityRow] entity_row_create returned no id for "${token}"`,
3264
+ context: { token, detail: data }
3265
+ });
3266
+ return { ok: false, error: msg };
3267
+ }
3268
+ const id = row.id;
3269
+ const named = typeof row.title === "string" && row.title ? row.title : title;
3270
+ titles.prime(token, id, named);
3271
+ return { ok: true, data: { id, title: named } };
3265
3272
  } catch (e) {
3266
3273
  const msg = e instanceof Error ? e.message : "Failed to create";
3267
3274
  errorSink({
@@ -3272,21 +3279,27 @@ function createEntityRowsService(deps, titles) {
3272
3279
  return { ok: false, error: msg };
3273
3280
  }
3274
3281
  },
3275
- /** Update the registry `titleColumn` of one row of `token`'s table. */
3282
+ /**
3283
+ * Rename one row of `token`'s table through `public.entity_row_rename`. The door
3284
+ * decides on the one ladder — the row's author, `editor` on the row, or a platform
3285
+ * admin — and answers "there is no such thing here" rather than telling a caller
3286
+ * that somebody else's row exists.
3287
+ */
3276
3288
  async renameEntityRow(token, id, title) {
3277
3289
  const gate = requireTitleColumn(token, "renaming rows");
3278
3290
  if (!gate.ok) return gate;
3279
- const info = registry.getEntityInfo(token);
3280
3291
  const trimmed = title.trim();
3281
3292
  if (!trimmed) return { ok: false, error: "Name is required" };
3282
3293
  try {
3283
- const table = tableFor(token, info.schema, info.table);
3284
- if (!table.ok) return table;
3285
- const { error } = await table.query.update({ [gate.titleColumn]: trimmed }).eq("id", id);
3294
+ const { error } = await dataSource.rpc("entity_row_rename", {
3295
+ p_token: token,
3296
+ p_id: id,
3297
+ p_title: trimmed
3298
+ });
3286
3299
  if (error) {
3287
3300
  errorSink({
3288
3301
  code: "entity_row_update_failed",
3289
- message: `[renameEntityRow] update failed for "${token}": ${error.message}`,
3302
+ message: `[renameEntityRow] entity_row_rename failed for "${token}": ${error.message}`,
3290
3303
  context: { token, id, detail: error }
3291
3304
  });
3292
3305
  return { ok: false, error: error.message };