@ai-matrx/records 0.8.0 → 0.11.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.
@@ -1598,6 +1598,24 @@ var DOORS = {
1598
1598
  fieldDeclare: "field_declare",
1599
1599
  fieldUpdate: "field_update",
1600
1600
  fieldRetire: "field_retire",
1601
+ // CUSTOM FIELDS ON A STANDARD BUSINESS TABLE. Every door above is keyed by a
1602
+ // custom Table's uuid, and a standard table has no Table record - so until
1603
+ // 2026-09-20 `custom.applicable_fields(org, 'party', null)` answered `22P02
1604
+ // invalid input syntax for uuid` and there was no other way in. These are
1605
+ // keyed by the REGISTRY TOKEN instead, and they are one set for all 643
1606
+ // tables the registry types Entity or Detail. The three value doors are
1607
+ // SECURITY INVOKER in the database on purpose: the standard table's own
1608
+ // row-level security is what decides who may read and write its rows, and a
1609
+ // definer wrapper would replace it with a second access system.
1610
+ entityTable: "entity_table",
1611
+ entityFields: "entity_fields",
1612
+ entityFieldDeclare: "entity_field_declare",
1613
+ entityFieldUpdate: "entity_field_update",
1614
+ entityFieldRetire: "entity_field_retire",
1615
+ entityFieldRights: "entity_field_rights",
1616
+ entityRecordRead: "entity_record_read",
1617
+ entityValueWrite: "entity_value_write",
1618
+ entityRecordsFind: "entity_records_find",
1601
1619
  tableCapacity: "table_capacity",
1602
1620
  tableStorage: "table_storage",
1603
1621
  promoteTable: "promote_table",
@@ -1704,6 +1722,23 @@ var DOORS = {
1704
1722
  workSlotRelease: "work_slot_release",
1705
1723
  workSlotHolds: "work_slot_holds",
1706
1724
  workSlotExpire: "work_slot_expire",
1725
+ // THE WORK LAYER'S OWN DOORS (lane WORK-DOORS, 2026-09-20). Until this lane
1726
+ // all nineteen `custom.work_*` functions were SECURITY INVOKER with no client
1727
+ // grant: REC-69, REC-70 and REC-71 were live in the store and unreachable
1728
+ // from a browser. These are the verbs a person actually uses.
1729
+ workPerson: "work_person",
1730
+ workAssign: "work_assign",
1731
+ workRecordStates: "work_record_states",
1732
+ workSetState: "work_set_state",
1733
+ workList: "work_list",
1734
+ workTemplates: "work_templates",
1735
+ /** THE ONE QUEUE: assignments, approvals and the agent's proposals together. */
1736
+ workInbox: "work_inbox",
1737
+ workApprovalApprovers: "work_approval_approvers",
1738
+ workApprovalRequest: "work_approval_request",
1739
+ workApprovalMayDecide: "work_approval_may_decide",
1740
+ workApprovalDecide: "work_approval_decide",
1741
+ workApprovalRead: "work_approval_read",
1707
1742
  // Declared here BECAUSE they do not exist yet: naming them is what makes the
1708
1743
  // absence visible to `pnpm check:store-registry` and to the suite.
1709
1744
  metadataSearch: "metadata_search",
@@ -2129,6 +2164,88 @@ function createRecordsClient(config) {
2129
2164
  "fieldDeclare"
2130
2165
  );
2131
2166
  },
2167
+ async entityTable({ token }) {
2168
+ const answer = await callDoor(
2169
+ DOORS.entityTable,
2170
+ { p_token: token },
2171
+ "entityTable"
2172
+ );
2173
+ if (!answer.ok) return err(answer.error);
2174
+ const row = Array.isArray(answer.data) ? answer.data[0] : answer.data;
2175
+ if (!row) {
2176
+ return err({
2177
+ code: "not_found",
2178
+ message: `The registry answered nothing for the table "${token}".`,
2179
+ hint: "REC-33: a standard table is named by its registry token. Nothing was read."
2180
+ });
2181
+ }
2182
+ return ok(row);
2183
+ },
2184
+ async entityFields({ token }) {
2185
+ const rows = await callDoor(
2186
+ DOORS.entityFields,
2187
+ { p_organization_id: org, p_token: token },
2188
+ "entityFields"
2189
+ );
2190
+ if (!rows.ok) return err(rows.error);
2191
+ return ok((rows.data ?? []).map((row) => ({ id: row.id, ...row.data })));
2192
+ },
2193
+ async entityFieldDeclare({ token, spec }) {
2194
+ return callDoor(
2195
+ DOORS.entityFieldDeclare,
2196
+ { p_organization_id: org, p_token: token, p_spec: spec },
2197
+ "entityFieldDeclare"
2198
+ );
2199
+ },
2200
+ async entityFieldUpdate({ field_id, patch }) {
2201
+ return callDoor(
2202
+ DOORS.entityFieldUpdate,
2203
+ { p_organization_id: org, p_field_id: field_id, p_patch: patch },
2204
+ "entityFieldUpdate"
2205
+ );
2206
+ },
2207
+ async entityFieldRetire({ field_id }) {
2208
+ return callDoor(
2209
+ DOORS.entityFieldRetire,
2210
+ { p_organization_id: org, p_field_id: field_id },
2211
+ "entityFieldRetire"
2212
+ );
2213
+ },
2214
+ async entityFieldRights({ token }) {
2215
+ return callDoor(
2216
+ DOORS.entityFieldRights,
2217
+ { p_organization_id: org, p_token: token },
2218
+ "entityFieldRights"
2219
+ );
2220
+ },
2221
+ async entityRecordRead({ token, record_id }) {
2222
+ return callDoor(
2223
+ DOORS.entityRecordRead,
2224
+ { p_organization_id: org, p_token: token, p_record_id: record_id },
2225
+ "entityRecordRead"
2226
+ );
2227
+ },
2228
+ async entityValueWrite({ token, record_id, patch }) {
2229
+ return callDoor(
2230
+ DOORS.entityValueWrite,
2231
+ { p_organization_id: org, p_token: token, p_record_id: record_id, p_patch: patch },
2232
+ "entityValueWrite"
2233
+ );
2234
+ },
2235
+ async entityRecordsFind({ token, key, value, limit, offset }) {
2236
+ return callDoor(
2237
+ DOORS.entityRecordsFind,
2238
+ {
2239
+ p_organization_id: org,
2240
+ p_token: token,
2241
+ p_key: key,
2242
+ p_value: value === void 0 ? null : value,
2243
+ ...limit === void 0 ? {} : { p_limit: limit },
2244
+ ...offset === void 0 ? {} : { p_offset: offset }
2245
+ },
2246
+ "entityRecordsFind"
2247
+ );
2248
+ },
2132
2249
  async fieldUpdate({ field_id, patch }) {
2133
2250
  return callDoor(
2134
2251
  DOORS.fieldUpdate,
@@ -2546,6 +2663,128 @@ function createRecordsClient(config) {
2546
2663
  "workSlotExpire"
2547
2664
  );
2548
2665
  },
2666
+ // ── the work layer a person actually uses ────────────────────────────
2667
+ async workInbox(args) {
2668
+ return callDoor(
2669
+ DOORS.workInbox,
2670
+ {
2671
+ p_organization_id: org,
2672
+ p_limit: args?.limit ?? 50,
2673
+ p_offset: args?.offset ?? 0,
2674
+ p_include_decided: args?.includeDecided ?? false
2675
+ },
2676
+ "workInbox"
2677
+ );
2678
+ },
2679
+ async workList(args) {
2680
+ return callDoor(
2681
+ DOORS.workList,
2682
+ {
2683
+ p_organization_id: org,
2684
+ p_flavour: args?.flavour ?? "mine",
2685
+ p_include_finished: args?.includeFinished ?? false,
2686
+ p_limit: args?.limit ?? 100,
2687
+ p_offset: args?.offset ?? 0
2688
+ },
2689
+ "workList"
2690
+ );
2691
+ },
2692
+ async workAssign({ record_id, user_id = null, dueDate = null, clearDue = false }) {
2693
+ return callDoor(
2694
+ DOORS.workAssign,
2695
+ {
2696
+ p_organization_id: org,
2697
+ p_record_id: record_id,
2698
+ p_assignee_user_id: user_id,
2699
+ p_due_date: dueDate,
2700
+ p_clear_due: clearDue
2701
+ },
2702
+ "workAssign"
2703
+ );
2704
+ },
2705
+ async workRecordStates({ record_id }) {
2706
+ return callDoor(
2707
+ DOORS.workRecordStates,
2708
+ { p_organization_id: org, p_record_id: record_id },
2709
+ "workRecordStates"
2710
+ );
2711
+ },
2712
+ async workSetState({ record_id, state_id }) {
2713
+ return callDoor(
2714
+ DOORS.workSetState,
2715
+ { p_organization_id: org, p_record_id: record_id, p_state_id: state_id },
2716
+ "workSetState"
2717
+ );
2718
+ },
2719
+ async workPerson({ user_id, create = true }) {
2720
+ return callDoor(
2721
+ DOORS.workPerson,
2722
+ { p_organization_id: org, p_user_id: user_id, p_create: create },
2723
+ "workPerson"
2724
+ );
2725
+ },
2726
+ async workTemplates(args) {
2727
+ return callDoor(
2728
+ DOORS.workTemplates,
2729
+ { p_organization_id: org, p_limit: args?.limit ?? 100 },
2730
+ "workTemplates"
2731
+ );
2732
+ },
2733
+ async workApprovalApprovers({ subject_id, approver_id = null }) {
2734
+ return callDoor(
2735
+ DOORS.workApprovalApprovers,
2736
+ { p_organization_id: org, p_subject_id: subject_id, p_approver_id: approver_id },
2737
+ "workApprovalApprovers"
2738
+ );
2739
+ },
2740
+ async workApprovalRequest({
2741
+ subject_id,
2742
+ change,
2743
+ note = null,
2744
+ approver_id = null,
2745
+ origin = "person",
2746
+ conversation_id = null
2747
+ }) {
2748
+ return callDoor(
2749
+ DOORS.workApprovalRequest,
2750
+ {
2751
+ p_organization_id: org,
2752
+ p_subject_id: subject_id,
2753
+ p_change: change,
2754
+ p_note: note,
2755
+ p_approver_id: approver_id,
2756
+ p_origin: origin,
2757
+ p_conversation_id: conversation_id
2758
+ },
2759
+ "workApprovalRequest"
2760
+ );
2761
+ },
2762
+ async workApprovalMayDecide({ approval_id }) {
2763
+ return callDoor(
2764
+ DOORS.workApprovalMayDecide,
2765
+ { p_organization_id: org, p_approval_id: approval_id },
2766
+ "workApprovalMayDecide"
2767
+ );
2768
+ },
2769
+ async workApprovalDecide({ approval_id, approve, note = null }) {
2770
+ return callDoor(
2771
+ DOORS.workApprovalDecide,
2772
+ {
2773
+ p_organization_id: org,
2774
+ p_approval_id: approval_id,
2775
+ p_approve: approve,
2776
+ p_note: note
2777
+ },
2778
+ "workApprovalDecide"
2779
+ );
2780
+ },
2781
+ async workApprovalRead({ approval_id }) {
2782
+ return callDoor(
2783
+ DOORS.workApprovalRead,
2784
+ { p_organization_id: org, p_approval_id: approval_id },
2785
+ "workApprovalRead"
2786
+ );
2787
+ },
2549
2788
  // ── the trust doors ──────────────────────────────────────────────────
2550
2789
  async isExternalPrincipal(args) {
2551
2790
  return trustDoor(
@@ -2872,6 +3111,72 @@ function useRecordMutation() {
2872
3111
  [client, run, saving, error, conflict]
2873
3112
  );
2874
3113
  }
3114
+ function useEntityFields(token) {
3115
+ return useAsync(
3116
+ (client) => token ? client.entityFields({ token }) : Promise.resolve({ ok: true, data: [] }),
3117
+ [token]
3118
+ );
3119
+ }
3120
+ function useEntityRecord(token, recordId) {
3121
+ return useAsync(
3122
+ (client) => token && recordId ? client.entityRecordRead({ token, record_id: recordId }) : Promise.resolve({ ok: true, data: null }),
3123
+ [token, recordId]
3124
+ );
3125
+ }
3126
+ function useEntityTable(token) {
3127
+ return useAsync(
3128
+ (client) => token ? client.entityTable({ token }) : Promise.resolve({ ok: true, data: null }),
3129
+ [token]
3130
+ );
3131
+ }
3132
+ function useEntityFieldRights(token) {
3133
+ return useAsync(
3134
+ (client) => token ? client.entityFieldRights({ token }) : Promise.resolve({ ok: true, data: null }),
3135
+ [token]
3136
+ );
3137
+ }
3138
+ function useEntityFieldMutation() {
3139
+ const client = useRecordsClient();
3140
+ const [saving, setSaving] = useState(false);
3141
+ const [error, setError] = useState(null);
3142
+ const run = useCallback(
3143
+ async (call, whenRefused) => {
3144
+ setSaving(true);
3145
+ setError(null);
3146
+ try {
3147
+ const result = await call();
3148
+ if (result.ok) return result.data;
3149
+ setError(result.error);
3150
+ return whenRefused;
3151
+ } finally {
3152
+ setSaving(false);
3153
+ }
3154
+ },
3155
+ []
3156
+ );
3157
+ return useMemo2(
3158
+ () => ({
3159
+ declare: (args) => run(() => client.entityFieldDeclare({ token: args.token, spec: args.spec }), null),
3160
+ update: (args) => run(
3161
+ () => client.entityFieldUpdate({ field_id: args.field_id, patch: args.patch }),
3162
+ null
3163
+ ),
3164
+ retire: (args) => run(() => client.entityFieldRetire({ field_id: args.field_id }), null),
3165
+ write: (args) => run(
3166
+ () => client.entityValueWrite({
3167
+ token: args.token,
3168
+ record_id: args.record_id,
3169
+ patch: args.patch
3170
+ }),
3171
+ null
3172
+ ),
3173
+ saving,
3174
+ error,
3175
+ clearError: () => setError(null)
3176
+ }),
3177
+ [client, run, saving, error]
3178
+ );
3179
+ }
2875
3180
  function useFieldMutation() {
2876
3181
  const client = useRecordsClient();
2877
3182
  const [saving, setSaving] = useState(false);
@@ -3052,6 +3357,11 @@ export {
3052
3357
  measureKey,
3053
3358
  ok,
3054
3359
  publicFormPath,
3360
+ useEntityFieldMutation,
3361
+ useEntityFieldRights,
3362
+ useEntityFields,
3363
+ useEntityRecord,
3364
+ useEntityTable,
3055
3365
  useFieldMutation,
3056
3366
  useFields,
3057
3367
  useMergeField,