@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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,55 @@
1
1
  # Changelog — @ai-matrx/records
2
2
 
3
+ ## 0.11.0
4
+
5
+ **The publish gate stops red-lighting on other lanes' migrations.** `the
6
+ generated door catalogue is the store's` asserted `STORE_DOORS.length === live`,
7
+ so every publish failed in which anybody anywhere had shipped a new `custom`
8
+ routine — 337 mirrored against 342 live on 2026-09-20, and not one of the five
9
+ was this package's. A release that red-lights on somebody else's work teaches
10
+ everyone to ignore red.
11
+
12
+ What the package must be right about is asserted and still gates: **every door
13
+ this mirror names exists in the live store**. A name here the store does not
14
+ have is this package claiming a door it cannot open, which is the whole reason
15
+ `store.generated.ts` is generated rather than typed. Doors the store has and the
16
+ mirror has not seen are REPORTED by name, loudly, and gate nothing.
17
+
18
+ ### Consumer action
19
+
20
+ None. No API changed.
21
+
22
+ ## 0.10.0
23
+
24
+ **The work layer has client doors, and this package can reach them.** Until lane
25
+ WORK-DOORS (2026-09-20) all nineteen `custom.work_*` functions were SECURITY
26
+ INVOKER, held no EXECUTE for `authenticated` and carried zero rows in
27
+ `platform.client_callable_door`: REC-69 (assignment and action state), REC-70
28
+ (template instantiation) and REC-71 (the slot hold) were live in the store and
29
+ unreachable from a browser. Thirteen new client methods, all against doors that
30
+ ask the one ladder first:
31
+
32
+ * `workInbox` — **THE ONE QUEUE.** Assignments, approvals and the agent's
33
+ proposals in one ordered list with one row shape (PRODUCTS.md row 6).
34
+ * `workList` — "my work", "work I assigned", "waiting on somebody being chosen",
35
+ across every Table in the organization, every row decided by the one ladder.
36
+ * `workAssign` — the Assignee value AND editor access, in one transaction. An
37
+ assignment that did not give access put a row in somebody's inbox that they
38
+ were refused when they opened it.
39
+ * `workRecordStates` / `workSetState` — the moves the workflow model allows, with
40
+ the sentence for each one it does not, so a screen offers real moves.
41
+ * `workApprovalRequest` / `workApprovalMayDecide` / `workApprovalDecide` /
42
+ `workApprovalRead` / `workApprovalApprovers` — asking for a change instead of
43
+ making it, and a decision that **applies** the change in the same transaction.
44
+ * `workPerson`, `workTemplates`.
45
+
46
+ New types in `work.ts`: `WorkInboxItem`, `WorkListItem`, `WorkRecordState`,
47
+ `WorkApprover`, `WorkApprovalFiled`, `WorkApprovalDecision`, `WorkAssignment`,
48
+ `WorkChange`, `WorkInboxKind`, `WorkOrigin`, `WorkDueState`, `WorkListFlavour`.
49
+
50
+ **Consumer action:** none required — every addition is new surface. A host that
51
+ wants the inbox takes `@ai-matrx/records-ui` 0.15.0 with it.
52
+
3
53
  ## 0.7.2
4
54
 
5
55
  **The door catalogue, regenerated while the store was still growing.** 0.7.1
@@ -1755,6 +1755,24 @@ var DOORS = {
1755
1755
  fieldDeclare: "field_declare",
1756
1756
  fieldUpdate: "field_update",
1757
1757
  fieldRetire: "field_retire",
1758
+ // CUSTOM FIELDS ON A STANDARD BUSINESS TABLE. Every door above is keyed by a
1759
+ // custom Table's uuid, and a standard table has no Table record - so until
1760
+ // 2026-09-20 `custom.applicable_fields(org, 'party', null)` answered `22P02
1761
+ // invalid input syntax for uuid` and there was no other way in. These are
1762
+ // keyed by the REGISTRY TOKEN instead, and they are one set for all 643
1763
+ // tables the registry types Entity or Detail. The three value doors are
1764
+ // SECURITY INVOKER in the database on purpose: the standard table's own
1765
+ // row-level security is what decides who may read and write its rows, and a
1766
+ // definer wrapper would replace it with a second access system.
1767
+ entityTable: "entity_table",
1768
+ entityFields: "entity_fields",
1769
+ entityFieldDeclare: "entity_field_declare",
1770
+ entityFieldUpdate: "entity_field_update",
1771
+ entityFieldRetire: "entity_field_retire",
1772
+ entityFieldRights: "entity_field_rights",
1773
+ entityRecordRead: "entity_record_read",
1774
+ entityValueWrite: "entity_value_write",
1775
+ entityRecordsFind: "entity_records_find",
1758
1776
  tableCapacity: "table_capacity",
1759
1777
  tableStorage: "table_storage",
1760
1778
  promoteTable: "promote_table",
@@ -1861,6 +1879,23 @@ var DOORS = {
1861
1879
  workSlotRelease: "work_slot_release",
1862
1880
  workSlotHolds: "work_slot_holds",
1863
1881
  workSlotExpire: "work_slot_expire",
1882
+ // THE WORK LAYER'S OWN DOORS (lane WORK-DOORS, 2026-09-20). Until this lane
1883
+ // all nineteen `custom.work_*` functions were SECURITY INVOKER with no client
1884
+ // grant: REC-69, REC-70 and REC-71 were live in the store and unreachable
1885
+ // from a browser. These are the verbs a person actually uses.
1886
+ workPerson: "work_person",
1887
+ workAssign: "work_assign",
1888
+ workRecordStates: "work_record_states",
1889
+ workSetState: "work_set_state",
1890
+ workList: "work_list",
1891
+ workTemplates: "work_templates",
1892
+ /** THE ONE QUEUE: assignments, approvals and the agent's proposals together. */
1893
+ workInbox: "work_inbox",
1894
+ workApprovalApprovers: "work_approval_approvers",
1895
+ workApprovalRequest: "work_approval_request",
1896
+ workApprovalMayDecide: "work_approval_may_decide",
1897
+ workApprovalDecide: "work_approval_decide",
1898
+ workApprovalRead: "work_approval_read",
1864
1899
  // Declared here BECAUSE they do not exist yet: naming them is what makes the
1865
1900
  // absence visible to `pnpm check:store-registry` and to the suite.
1866
1901
  metadataSearch: "metadata_search",
@@ -2294,6 +2329,88 @@ function createRecordsClient(config) {
2294
2329
  "fieldDeclare"
2295
2330
  );
2296
2331
  },
2332
+ async entityTable({ token }) {
2333
+ const answer = await callDoor(
2334
+ DOORS.entityTable,
2335
+ { p_token: token },
2336
+ "entityTable"
2337
+ );
2338
+ if (!answer.ok) return err(answer.error);
2339
+ const row = Array.isArray(answer.data) ? answer.data[0] : answer.data;
2340
+ if (!row) {
2341
+ return err({
2342
+ code: "not_found",
2343
+ message: `The registry answered nothing for the table "${token}".`,
2344
+ hint: "REC-33: a standard table is named by its registry token. Nothing was read."
2345
+ });
2346
+ }
2347
+ return ok(row);
2348
+ },
2349
+ async entityFields({ token }) {
2350
+ const rows = await callDoor(
2351
+ DOORS.entityFields,
2352
+ { p_organization_id: org, p_token: token },
2353
+ "entityFields"
2354
+ );
2355
+ if (!rows.ok) return err(rows.error);
2356
+ return ok((rows.data ?? []).map((row) => ({ id: row.id, ...row.data })));
2357
+ },
2358
+ async entityFieldDeclare({ token, spec }) {
2359
+ return callDoor(
2360
+ DOORS.entityFieldDeclare,
2361
+ { p_organization_id: org, p_token: token, p_spec: spec },
2362
+ "entityFieldDeclare"
2363
+ );
2364
+ },
2365
+ async entityFieldUpdate({ field_id, patch }) {
2366
+ return callDoor(
2367
+ DOORS.entityFieldUpdate,
2368
+ { p_organization_id: org, p_field_id: field_id, p_patch: patch },
2369
+ "entityFieldUpdate"
2370
+ );
2371
+ },
2372
+ async entityFieldRetire({ field_id }) {
2373
+ return callDoor(
2374
+ DOORS.entityFieldRetire,
2375
+ { p_organization_id: org, p_field_id: field_id },
2376
+ "entityFieldRetire"
2377
+ );
2378
+ },
2379
+ async entityFieldRights({ token }) {
2380
+ return callDoor(
2381
+ DOORS.entityFieldRights,
2382
+ { p_organization_id: org, p_token: token },
2383
+ "entityFieldRights"
2384
+ );
2385
+ },
2386
+ async entityRecordRead({ token, record_id }) {
2387
+ return callDoor(
2388
+ DOORS.entityRecordRead,
2389
+ { p_organization_id: org, p_token: token, p_record_id: record_id },
2390
+ "entityRecordRead"
2391
+ );
2392
+ },
2393
+ async entityValueWrite({ token, record_id, patch }) {
2394
+ return callDoor(
2395
+ DOORS.entityValueWrite,
2396
+ { p_organization_id: org, p_token: token, p_record_id: record_id, p_patch: patch },
2397
+ "entityValueWrite"
2398
+ );
2399
+ },
2400
+ async entityRecordsFind({ token, key, value, limit, offset }) {
2401
+ return callDoor(
2402
+ DOORS.entityRecordsFind,
2403
+ {
2404
+ p_organization_id: org,
2405
+ p_token: token,
2406
+ p_key: key,
2407
+ p_value: value === void 0 ? null : value,
2408
+ ...limit === void 0 ? {} : { p_limit: limit },
2409
+ ...offset === void 0 ? {} : { p_offset: offset }
2410
+ },
2411
+ "entityRecordsFind"
2412
+ );
2413
+ },
2297
2414
  async fieldUpdate({ field_id, patch }) {
2298
2415
  return callDoor(
2299
2416
  DOORS.fieldUpdate,
@@ -2711,6 +2828,128 @@ function createRecordsClient(config) {
2711
2828
  "workSlotExpire"
2712
2829
  );
2713
2830
  },
2831
+ // ── the work layer a person actually uses ────────────────────────────
2832
+ async workInbox(args) {
2833
+ return callDoor(
2834
+ DOORS.workInbox,
2835
+ {
2836
+ p_organization_id: org,
2837
+ p_limit: args?.limit ?? 50,
2838
+ p_offset: args?.offset ?? 0,
2839
+ p_include_decided: args?.includeDecided ?? false
2840
+ },
2841
+ "workInbox"
2842
+ );
2843
+ },
2844
+ async workList(args) {
2845
+ return callDoor(
2846
+ DOORS.workList,
2847
+ {
2848
+ p_organization_id: org,
2849
+ p_flavour: args?.flavour ?? "mine",
2850
+ p_include_finished: args?.includeFinished ?? false,
2851
+ p_limit: args?.limit ?? 100,
2852
+ p_offset: args?.offset ?? 0
2853
+ },
2854
+ "workList"
2855
+ );
2856
+ },
2857
+ async workAssign({ record_id, user_id = null, dueDate = null, clearDue = false }) {
2858
+ return callDoor(
2859
+ DOORS.workAssign,
2860
+ {
2861
+ p_organization_id: org,
2862
+ p_record_id: record_id,
2863
+ p_assignee_user_id: user_id,
2864
+ p_due_date: dueDate,
2865
+ p_clear_due: clearDue
2866
+ },
2867
+ "workAssign"
2868
+ );
2869
+ },
2870
+ async workRecordStates({ record_id }) {
2871
+ return callDoor(
2872
+ DOORS.workRecordStates,
2873
+ { p_organization_id: org, p_record_id: record_id },
2874
+ "workRecordStates"
2875
+ );
2876
+ },
2877
+ async workSetState({ record_id, state_id }) {
2878
+ return callDoor(
2879
+ DOORS.workSetState,
2880
+ { p_organization_id: org, p_record_id: record_id, p_state_id: state_id },
2881
+ "workSetState"
2882
+ );
2883
+ },
2884
+ async workPerson({ user_id, create = true }) {
2885
+ return callDoor(
2886
+ DOORS.workPerson,
2887
+ { p_organization_id: org, p_user_id: user_id, p_create: create },
2888
+ "workPerson"
2889
+ );
2890
+ },
2891
+ async workTemplates(args) {
2892
+ return callDoor(
2893
+ DOORS.workTemplates,
2894
+ { p_organization_id: org, p_limit: args?.limit ?? 100 },
2895
+ "workTemplates"
2896
+ );
2897
+ },
2898
+ async workApprovalApprovers({ subject_id, approver_id = null }) {
2899
+ return callDoor(
2900
+ DOORS.workApprovalApprovers,
2901
+ { p_organization_id: org, p_subject_id: subject_id, p_approver_id: approver_id },
2902
+ "workApprovalApprovers"
2903
+ );
2904
+ },
2905
+ async workApprovalRequest({
2906
+ subject_id,
2907
+ change,
2908
+ note = null,
2909
+ approver_id = null,
2910
+ origin = "person",
2911
+ conversation_id = null
2912
+ }) {
2913
+ return callDoor(
2914
+ DOORS.workApprovalRequest,
2915
+ {
2916
+ p_organization_id: org,
2917
+ p_subject_id: subject_id,
2918
+ p_change: change,
2919
+ p_note: note,
2920
+ p_approver_id: approver_id,
2921
+ p_origin: origin,
2922
+ p_conversation_id: conversation_id
2923
+ },
2924
+ "workApprovalRequest"
2925
+ );
2926
+ },
2927
+ async workApprovalMayDecide({ approval_id }) {
2928
+ return callDoor(
2929
+ DOORS.workApprovalMayDecide,
2930
+ { p_organization_id: org, p_approval_id: approval_id },
2931
+ "workApprovalMayDecide"
2932
+ );
2933
+ },
2934
+ async workApprovalDecide({ approval_id, approve, note = null }) {
2935
+ return callDoor(
2936
+ DOORS.workApprovalDecide,
2937
+ {
2938
+ p_organization_id: org,
2939
+ p_approval_id: approval_id,
2940
+ p_approve: approve,
2941
+ p_note: note
2942
+ },
2943
+ "workApprovalDecide"
2944
+ );
2945
+ },
2946
+ async workApprovalRead({ approval_id }) {
2947
+ return callDoor(
2948
+ DOORS.workApprovalRead,
2949
+ { p_organization_id: org, p_approval_id: approval_id },
2950
+ "workApprovalRead"
2951
+ );
2952
+ },
2714
2953
  // ── the trust doors ──────────────────────────────────────────────────
2715
2954
  async isExternalPrincipal(args) {
2716
2955
  return trustDoor(