@ai-matrx/records 0.8.0 → 0.16.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,168 @@
1
1
  # Changelog — @ai-matrx/records
2
2
 
3
+ ## 0.16.0
4
+
5
+ **A column is declared, and a client type can finally say so.**
6
+
7
+ `NewFieldDeclaration` now names what `custom.field_declare` has actually taken
8
+ since 2026-09-20: `type` (the one word every agent, script and import reaches
9
+ for — the store resolves the thirteen parity types, the five behaviours and the
10
+ plain synonyms, and refuses a word that means nothing by name), `config` (a long
11
+ text's `multiline`, a list's existing options table — the door always read it and
12
+ no client could send it), `relation_target` and `on_target_delete` (a column that
13
+ points at another of this organization's own tables, which no client type could
14
+ express at all), and `format` (the one shape `custom.doc_sign` accepts).
15
+
16
+ `FieldPatch` gains the door's BEHAVIOUR arm — `parity_type`, `plain`, `type`,
17
+ `multi` — plus `relation_target`, `on_target_delete`, `promoted`, `unique` and
18
+ `depends_on`. It named only the settings, so the one caller that needed to move a
19
+ column back onto the behaviour it is written against had no door and reached for
20
+ `custom.record_update` instead, writing the document *under* the guards rather
21
+ than through them. **`multi` is read only inside that arm: send the behaviour
22
+ word with it or nothing happens.**
23
+
24
+ **The columns come back in the order they were declared.** `custom.applicable_fields`
25
+ answers a SET — its order is the plan's and it moves between calls — so every
26
+ consumer of `client.fields()` was drawing columns in an arbitrary order. A table
27
+ declared Title, Day rate, Due came back Day rate, Title, Due. The Field's own
28
+ `sort` is applied once, here, so every screen, export, form and agent inherits it.
29
+
30
+ **22007 is mapped.** The live-door census caught `custom.dashboard_window_sql`
31
+ raising it; it reads as `invalid_argument`, like 42703 before it.
32
+
33
+ **The live-door suite declared its own fixture the way the store no longer
34
+ allows** — `custom.record_write` into the field kernel — so eighteen of its
35
+ thirty-three clauses were red on `main` against the live store. It uses
36
+ `custom.field_declare`. 33/33.
37
+ ## 0.15.0
38
+
39
+ **A client portal has an owner's side, and this package can reach it.**
40
+ `custom.portals`, `custom.portal_card`, `custom.portal_declare`,
41
+ `custom.portal_invite`, `custom.portal_revoke` and `custom.portal_preview` have
42
+ been live on the database and no client could call them, so the six doors that
43
+ decide who signs in from outside an organization — and what they see — existed
44
+ with nothing able to ask them. `store.generated.ts` was regenerated from the
45
+ live store (372 → 387 doors) and the six are now on `client`:
46
+
47
+ - `client.portals()` — every portal over this organization, with its client
48
+ Table, how many Tables it exposes, how many people are invited and how many
49
+ have actually signed in. The store filters the list on whether you may open
50
+ the client Table, so it never reveals a Table.
51
+ - `client.portalCard({ portal_id })` — one portal in full: each exposed Table
52
+ with the relation Field that says whose a record is and the fields a client
53
+ sees and may change, every person with `signed_in` and `is_active` kept
54
+ APART, and `external_lane_open`.
55
+ - `client.portalDeclare(...)` — create or RE-STATE one. Re-stating replaces
56
+ what the portal exposes and leaves the people alone.
57
+ - `client.portalInvite({ portal_id, client_record_id, email })` — and it takes
58
+ no `user_id` on purpose. From a screen that value is always null: an
59
+ invitation confers NOTHING until the person follows their own sign-in link,
60
+ which is what the door's own `say` sentence states. A client that passed an
61
+ id would be granting access on somebody else's behalf.
62
+ - `client.portalRevoke({ portal_id, principal_id })` — the answer's `say` names
63
+ the consequence in the past tense.
64
+ - `client.portalPreview({ portal_id, principal_id, table_id })` — "view as this
65
+ client". The door asks `custom.visible_set` for HER user id, the same call
66
+ `custom.read_records` makes when she opens the page, so it cannot disagree
67
+ with what she sees. It REFUSES (`02000`, mapped to `not_found`) when she has
68
+ not signed in, rather than answering an empty list.
69
+
70
+ New module `portal`, exported from the root: `PortalSummary`,
71
+ `PortalTableExposure`, `PortalPrincipal`, `PortalCard`, `PortalInvitation`,
72
+ `PortalRevocation`, `PortalPreviewRow`, and `portalPath(slug)` — the one place
73
+ `/portal/c/<slug>` is written down.
74
+
75
+ **Consumer action:** none required; every addition is new surface. A host that
76
+ already builds a portal address by hand should use `portalPath` so there is one
77
+ spelling of it.
78
+
79
+ ## 0.13.0
80
+
81
+ **A choice value is the choice's own word, and this package says what that means.**
82
+ A list Field's cell used to hold the option RECORD'S ID, so every read, filter,
83
+ group-by, export and agent got back a uuid — the seventh independent pass failed
84
+ acceptance test T8 on exactly that. The store now holds the option's own stable
85
+ key, the read doors hand back the LABEL and name the key beside it in
86
+ `_choices`, and a caller may write the label, the key or (so nothing that worked
87
+ yesterday breaks) the option's id.
88
+
89
+ New module `choice`, exported from the root: `optionKey`, `optionLabel`,
90
+ `isTheChosen`, `choiceValuesOf`, `choicesOf`, `holdsARetiredChoice`,
91
+ `choiceSlug`, `looksLikeAnId`, and the `ChoiceOption` type. `isTheChosen` is the
92
+ one a control wants: it recognises a choice by its key, its label or its option
93
+ id, which is what lets one picker read a document from any of the three eras.
94
+
95
+ **Consumer action:** a control that compared a cell to `option.id` must use
96
+ `isTheChosen` and write `optionKey(option)` — comparing against the id alone now
97
+ shows nothing selected, because the read door hands back the label.
98
+
99
+ ## 0.12.0
100
+
101
+ **A person can see what they are being told about, and switch one off.**
102
+ `custom.subscriptions` and `custom.subscription_mute` have been live on the
103
+ database since 20 September and no client could call them, so a form's "tell me
104
+ when somebody answers" could be turned ON by an agent and never turned off by
105
+ the person it was telling. `client.subscriptions({ table_id })` answers mine
106
+ plus anyone's over a Table I hold admin on — narrowed to Tables I can already
107
+ open, so the list never reveals one — and `client.subscriptionMute({ rule_id,
108
+ muted })` is the switch. `MySubscription` carries the two things a screen needs
109
+ and the notifier does not: `muted`, and `i_may_mute`.
110
+
111
+ `aggSubscriptions` is unchanged and is still the NOTIFIER's reader, which no
112
+ client can call. Muting is honoured inside that one reader, so a screen can
113
+ never say a subscription is off while it keeps firing.
114
+
115
+
116
+ ## 0.11.0
117
+
118
+ **The publish gate stops red-lighting on other lanes' migrations.** `the
119
+ generated door catalogue is the store's` asserted `STORE_DOORS.length === live`,
120
+ so every publish failed in which anybody anywhere had shipped a new `custom`
121
+ routine — 337 mirrored against 342 live on 2026-09-20, and not one of the five
122
+ was this package's. A release that red-lights on somebody else's work teaches
123
+ everyone to ignore red.
124
+
125
+ What the package must be right about is asserted and still gates: **every door
126
+ this mirror names exists in the live store**. A name here the store does not
127
+ have is this package claiming a door it cannot open, which is the whole reason
128
+ `store.generated.ts` is generated rather than typed. Doors the store has and the
129
+ mirror has not seen are REPORTED by name, loudly, and gate nothing.
130
+
131
+ ### Consumer action
132
+
133
+ None. No API changed.
134
+
135
+ ## 0.10.0
136
+
137
+ **The work layer has client doors, and this package can reach them.** Until lane
138
+ WORK-DOORS (2026-09-20) all nineteen `custom.work_*` functions were SECURITY
139
+ INVOKER, held no EXECUTE for `authenticated` and carried zero rows in
140
+ `platform.client_callable_door`: REC-69 (assignment and action state), REC-70
141
+ (template instantiation) and REC-71 (the slot hold) were live in the store and
142
+ unreachable from a browser. Thirteen new client methods, all against doors that
143
+ ask the one ladder first:
144
+
145
+ * `workInbox` — **THE ONE QUEUE.** Assignments, approvals and the agent's
146
+ proposals in one ordered list with one row shape (PRODUCTS.md row 6).
147
+ * `workList` — "my work", "work I assigned", "waiting on somebody being chosen",
148
+ across every Table in the organization, every row decided by the one ladder.
149
+ * `workAssign` — the Assignee value AND editor access, in one transaction. An
150
+ assignment that did not give access put a row in somebody's inbox that they
151
+ were refused when they opened it.
152
+ * `workRecordStates` / `workSetState` — the moves the workflow model allows, with
153
+ the sentence for each one it does not, so a screen offers real moves.
154
+ * `workApprovalRequest` / `workApprovalMayDecide` / `workApprovalDecide` /
155
+ `workApprovalRead` / `workApprovalApprovers` — asking for a change instead of
156
+ making it, and a decision that **applies** the change in the same transaction.
157
+ * `workPerson`, `workTemplates`.
158
+
159
+ New types in `work.ts`: `WorkInboxItem`, `WorkListItem`, `WorkRecordState`,
160
+ `WorkApprover`, `WorkApprovalFiled`, `WorkApprovalDecision`, `WorkAssignment`,
161
+ `WorkChange`, `WorkInboxKind`, `WorkOrigin`, `WorkDueState`, `WorkListFlavour`.
162
+
163
+ **Consumer action:** none required — every addition is new surface. A host that
164
+ wants the inbox takes `@ai-matrx/records-ui` 0.15.0 with it.
165
+
3
166
  ## 0.7.2
4
167
 
5
168
  **The door catalogue, regenerated while the store was still growing.** 0.7.1