@ai-matrx/records 0.11.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 +113 -0
- package/dist/core/index.cjs +285 -13
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +133 -5
- package/dist/core/index.d.ts +133 -5
- package/dist/core/index.js +285 -13
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +116 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +630 -10
- package/dist/index.d.ts +630 -10
- package/dist/index.js +116 -8
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +282 -10
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +747 -12
- package/dist/react/index.d.ts +747 -12
- package/dist/react/index.js +282 -10
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,118 @@
|
|
|
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
|
+
|
|
3
116
|
## 0.11.0
|
|
4
117
|
|
|
5
118
|
**The publish gate stops red-lighting on other lanes' migrations.** `the
|
package/dist/core/index.cjs
CHANGED
|
@@ -72,6 +72,9 @@ __export(core_exports, {
|
|
|
72
72
|
asWriteConflict: () => asWriteConflict,
|
|
73
73
|
atLeast: () => atLeast,
|
|
74
74
|
cellText: () => cellText,
|
|
75
|
+
choiceSlug: () => choiceSlug,
|
|
76
|
+
choiceValuesOf: () => choiceValuesOf,
|
|
77
|
+
choicesOf: () => choicesOf,
|
|
75
78
|
createRecordsClient: () => createRecordsClient,
|
|
76
79
|
doorAbsent: () => doorAbsent,
|
|
77
80
|
doorCensus: () => doorCensus,
|
|
@@ -80,15 +83,21 @@ __export(core_exports, {
|
|
|
80
83
|
exportCsv: () => exportCsv,
|
|
81
84
|
exportXlsx: () => exportXlsx,
|
|
82
85
|
highestLevel: () => highestLevel,
|
|
86
|
+
holdsARetiredChoice: () => holdsARetiredChoice,
|
|
83
87
|
importCsv: () => importCsv,
|
|
84
88
|
importXlsx: () => importXlsx,
|
|
85
89
|
intersectIds: () => intersectIds,
|
|
86
90
|
isRecordsErr: () => isRecordsErr,
|
|
91
|
+
isTheChosen: () => isTheChosen,
|
|
92
|
+
looksLikeAnId: () => looksLikeAnId,
|
|
87
93
|
mapPgError: () => mapPgError,
|
|
88
94
|
measureKey: () => measureKey,
|
|
89
95
|
ok: () => ok,
|
|
96
|
+
optionKey: () => optionKey,
|
|
97
|
+
optionLabel: () => optionLabel,
|
|
90
98
|
parseCsv: () => parseCsv,
|
|
91
99
|
planQuery: () => planQuery,
|
|
100
|
+
portalPath: () => portalPath,
|
|
92
101
|
predictEnvelopeRefusal: () => predictEnvelopeRefusal,
|
|
93
102
|
predictSizeRefusal: () => predictSizeRefusal,
|
|
94
103
|
predictValueRefusals: () => predictValueRefusals,
|
|
@@ -183,11 +192,59 @@ function highestLevel(left, right) {
|
|
|
183
192
|
return ORDINAL[left] >= ORDINAL[right] ? left : right;
|
|
184
193
|
}
|
|
185
194
|
|
|
195
|
+
// src/choice.ts
|
|
196
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
197
|
+
function optionKey(option) {
|
|
198
|
+
const stored = option.metadata?.["option_key"];
|
|
199
|
+
if (typeof stored === "string" && stored.trim() !== "") return stored;
|
|
200
|
+
return choiceSlug(optionLabel(option));
|
|
201
|
+
}
|
|
202
|
+
function optionLabel(option) {
|
|
203
|
+
const doc = option.data;
|
|
204
|
+
const title = doc?.["title"] ?? doc?.["name"];
|
|
205
|
+
if (typeof title === "string" && title.trim() !== "") return title;
|
|
206
|
+
return "Unnamed choice";
|
|
207
|
+
}
|
|
208
|
+
function choiceSlug(word) {
|
|
209
|
+
const slug = word.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 55);
|
|
210
|
+
return slug === "" ? "choice" : slug;
|
|
211
|
+
}
|
|
212
|
+
function isTheChosen(option, value) {
|
|
213
|
+
if (typeof value !== "string") return false;
|
|
214
|
+
const asked = value.trim().toLowerCase();
|
|
215
|
+
if (asked === "") return false;
|
|
216
|
+
return asked === optionKey(option).toLowerCase() || asked === optionLabel(option).toLowerCase() || asked === option.id.toLowerCase();
|
|
217
|
+
}
|
|
218
|
+
function choiceValuesOf(value) {
|
|
219
|
+
if (Array.isArray(value)) return value.filter((v) => typeof v === "string");
|
|
220
|
+
if (typeof value === "string" && value !== "") return [value];
|
|
221
|
+
return [];
|
|
222
|
+
}
|
|
223
|
+
function choicesOf(document, fieldKeyOrId) {
|
|
224
|
+
const block = document?.["_choices"];
|
|
225
|
+
if (!block || typeof block !== "object") return [];
|
|
226
|
+
const entry = block[fieldKeyOrId];
|
|
227
|
+
if (!entry) return [];
|
|
228
|
+
const list = Array.isArray(entry) ? entry : [entry];
|
|
229
|
+
return list.filter((x) => !!x && typeof x === "object" && typeof x.key === "string");
|
|
230
|
+
}
|
|
231
|
+
function holdsARetiredChoice(document, fieldKeyOrId) {
|
|
232
|
+
return choicesOf(document, fieldKeyOrId).some((c) => c.retired === true);
|
|
233
|
+
}
|
|
234
|
+
function looksLikeAnId(value) {
|
|
235
|
+
return typeof value === "string" && UUID.test(value);
|
|
236
|
+
}
|
|
237
|
+
|
|
186
238
|
// src/rule.ts
|
|
187
239
|
function publicFormPath(formId) {
|
|
188
240
|
return `/f/${formId}`;
|
|
189
241
|
}
|
|
190
242
|
|
|
243
|
+
// src/portal.ts
|
|
244
|
+
function portalPath(slug) {
|
|
245
|
+
return `/portal/c/${slug}`;
|
|
246
|
+
}
|
|
247
|
+
|
|
191
248
|
// src/aggregate.ts
|
|
192
249
|
function measureKey(measure) {
|
|
193
250
|
return measure.op === "count" ? "count" : `${measure.op}_${measure.key ?? ""}`;
|
|
@@ -302,6 +359,20 @@ var STORE_DOORS = [
|
|
|
302
359
|
{ name: "caller_role", args: "", returns: "name", security: "invoker" },
|
|
303
360
|
{ name: "carrying_edges_in", args: "p_organization_id uuid", returns: "TABLE(container_type text, container_id uuid, item_type text, item_id uuid, conveys_max permission_level)", security: "definer" },
|
|
304
361
|
{ name: "carrying_edges_of", args: "p_item_type text, p_item_id uuid", returns: "TABLE(container_type text, container_id uuid, conveys_max permission_level)", security: "definer" },
|
|
362
|
+
{ name: "choice_census", args: "p_organization_id uuid, p_table_id uuid DEFAULT NULL::uuid", returns: "jsonb", security: "definer" },
|
|
363
|
+
{ name: "choice_field_map", args: "p_organization_id uuid, p_table_id uuid", returns: "jsonb", security: "invoker" },
|
|
364
|
+
{ name: "choice_filter_normalize", args: "p_map jsonb, p_filter jsonb", returns: "jsonb", security: "invoker" },
|
|
365
|
+
{ name: "choice_key_for", args: "p_organization_id uuid, p_options_table_id uuid, p_title text, p_exclude uuid DEFAULT NULL::uuid", returns: "text", security: "invoker" },
|
|
366
|
+
{ name: "choice_key_of", args: "p_field jsonb, p_token text", returns: "text", security: "invoker" },
|
|
367
|
+
{ name: "choice_options", args: "p_organization_id uuid, p_options_table_id uuid", returns: "jsonb", security: "invoker" },
|
|
368
|
+
{ name: "choice_render", args: "p_organization_id uuid, p_table_id uuid, p_doc jsonb", returns: "jsonb", security: "invoker" },
|
|
369
|
+
{ name: "choice_render_groups", args: "p_map jsonb, p_groups jsonb", returns: "jsonb", security: "invoker" },
|
|
370
|
+
{ name: "choice_render_note", args: "p_field jsonb, p_value jsonb", returns: "jsonb", security: "invoker" },
|
|
371
|
+
{ name: "choice_render_value", args: "p_field jsonb, p_value jsonb", returns: "jsonb", security: "invoker" },
|
|
372
|
+
{ name: "choice_slug", args: "p_word text", returns: "text", security: "invoker" },
|
|
373
|
+
{ name: "choice_synonyms", args: "p_organization_id uuid, p_table_id uuid, p_token text", returns: "text[]", security: "invoker" },
|
|
374
|
+
{ name: "choice_synonyms_in", args: "p_map jsonb, p_token text", returns: "text[]", security: "invoker" },
|
|
375
|
+
{ name: "choice_words", args: "p_field jsonb", returns: "text", security: "invoker" },
|
|
305
376
|
{ name: "client_write_grants", args: "", returns: "TABLE(role_name text, object_name text, privilege text)", security: "invoker" },
|
|
306
377
|
{ name: "computed_provenance", args: "p_organization_id uuid, p_record_id uuid", returns: "TABLE(field_key text, field_id uuid, value jsonb, rule_id uuid, rule_version integer, computed_at timestamp with time zone)", security: "invoker" },
|
|
307
378
|
{ name: "containment_chain", args: "p_organization_id uuid, p_record_id uuid", returns: "TABLE(ancestor_id uuid, depth integer)", security: "invoker" },
|
|
@@ -310,6 +381,17 @@ var STORE_DOORS = [
|
|
|
310
381
|
{ name: "containment_parent", args: "p_data jsonb", returns: "uuid", security: "invoker" },
|
|
311
382
|
{ name: "cross_organization_links_open", args: "p_source_organization_id uuid, p_target_organization_id uuid", returns: "boolean", security: "invoker" },
|
|
312
383
|
{ name: "custom_fields_tables", args: "", returns: "TABLE(token text, schema_name text, table_name text)", security: "invoker" },
|
|
384
|
+
{ name: "dashboard_block_normalize", args: "p_organization_id uuid, p_subject_table_id uuid, p_block jsonb", returns: "jsonb", security: "definer" },
|
|
385
|
+
{ name: "dashboard_class", args: "", returns: "text", security: "invoker" },
|
|
386
|
+
{ name: "dashboard_declare", args: "p_organization_id uuid, p_table_id uuid, p_name text, p_blocks jsonb DEFAULT '[]'::jsonb, p_presentation jsonb DEFAULT '{}'::jsonb, p_dashboard_id uuid DEFAULT NULL::uuid", returns: "uuid", security: "definer" },
|
|
387
|
+
{ name: "dashboard_delete", args: "p_organization_id uuid, p_dashboard_id uuid", returns: "boolean", security: "definer" },
|
|
388
|
+
{ name: "dashboard_field_keys", args: "p_organization_id uuid, p_table_id uuid", returns: "text[]", security: "definer" },
|
|
389
|
+
{ name: "dashboard_kinds", args: "", returns: "text[]", security: "invoker" },
|
|
390
|
+
{ name: "dashboard_moment_sql", args: "p_key text", returns: "text", security: "invoker" },
|
|
391
|
+
{ name: "dashboard_run", args: "p_organization_id uuid, p_dashboard_id uuid, p_filter jsonb DEFAULT '{}'::jsonb", returns: "jsonb", security: "definer" },
|
|
392
|
+
{ name: "dashboard_stuck", args: "p_organization_id uuid, p_table_id uuid, p_state_key text, p_days integer DEFAULT 14, p_filter jsonb DEFAULT '{}'::jsonb, p_limit integer DEFAULT 50, p_required text DEFAULT 'viewer'::text", returns: "TABLE(record_id uuid, title text, state text, last_changed_at timestamp with time zone, days_unchanged numeric, measured_from text)", security: "definer" },
|
|
393
|
+
{ name: "dashboard_window_sql", args: "p_key text, p_window jsonb", returns: "text", security: "invoker" },
|
|
394
|
+
{ name: "dashboards", args: "p_organization_id uuid, p_table_id uuid DEFAULT NULL::uuid", returns: "TABLE(dashboard_id uuid, table_id uuid, name text, blocks jsonb, presentation jsonb, block_count integer, version integer, created_at timestamp with time zone, updated_at timestamp with time zone)", security: "definer" },
|
|
313
395
|
{ name: "delete_cascade_closure", args: "p_organization_id uuid, p_record_id uuid", returns: "uuid[]", security: "invoker" },
|
|
314
396
|
{ name: "delete_preview", args: "p_organization_id uuid, p_record_id uuid", returns: "jsonb", security: "definer" },
|
|
315
397
|
{ name: "delete_rule", args: "p_organization_id uuid, p_record_id uuid, p_apply boolean DEFAULT true", returns: "jsonb", security: "definer" },
|
|
@@ -406,16 +488,20 @@ var STORE_DOORS = [
|
|
|
406
488
|
{ name: "io_restore", args: "p_organization_id uuid, p_record_id uuid, p_version integer", returns: "integer", security: "definer" },
|
|
407
489
|
{ name: "io_revisions", args: "p_organization_id uuid, p_record_id uuid", returns: "TABLE(version integer, changed_at timestamp with time zone, changed_by uuid, summary text, operation text, changed_fields jsonb)", security: "definer" },
|
|
408
490
|
{ name: "is_a_retirement", args: "p_old_deleted timestamp with time zone, p_new_deleted timestamp with time zone, p_old_data jsonb, p_new_data jsonb, p_old_table uuid, p_new_table uuid, p_old_org uuid, p_new_org uuid, p_old_class text, p_new_class text", returns: "boolean", security: "invoker" },
|
|
491
|
+
{ name: "list_door_disagreements", args: "p_pretend text DEFAULT NULL::text, p_only_organization uuid DEFAULT NULL::uuid, p_sample integer DEFAULT 200", returns: "TABLE(organization_id uuid, organization_name text, member_id uuid, table_id uuid, record_id uuid, door text, why text)", security: "invoker" },
|
|
492
|
+
{ name: "list_door_disagreements", args: "p_pretend text, p_only_organization uuid, p_sample integer, p_exhaustive boolean", returns: "TABLE(organization_id uuid, organization_name text, member_id uuid, table_id uuid, record_id uuid, door text, why text)", security: "invoker" },
|
|
409
493
|
{ name: "lookup_value", args: "p_organization_id uuid, p_record_id uuid, p_field_data jsonb", returns: "jsonb", security: "invoker" },
|
|
410
494
|
{ name: "mask_document", args: "p_document jsonb, p_visible_keys text[], p_notices jsonb, p_by_id boolean DEFAULT false, p_key_ids jsonb DEFAULT '{}'::jsonb", returns: "jsonb", security: "invoker" },
|
|
411
495
|
{ name: "mask_document", args: "p_document jsonb, p_visible_keys text[], p_notices jsonb, p_by_id boolean DEFAULT false, p_key_ids jsonb DEFAULT '{}'::jsonb, p_declared_keys text[] DEFAULT NULL::text[]", returns: "jsonb", security: "invoker" },
|
|
412
496
|
{ name: "merge_field_kernel_id", args: "", returns: "uuid", security: "invoker" },
|
|
497
|
+
{ name: "migrate_choice_keys", args: "p_organization_id uuid, p_table_id uuid, p_dry_run boolean DEFAULT false", returns: "jsonb", security: "definer" },
|
|
413
498
|
{ name: "migrate_delete", args: "p_organization_id uuid, p_record_id uuid, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
414
499
|
{ name: "migrate_demote", args: "p_organization_id uuid, p_table_id uuid, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
415
500
|
{ name: "migrate_extract_parent", args: "p_organization_id uuid, p_id uuid, p_parent_table_id uuid, p_moved_keys text[], p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
416
501
|
{ name: "migrate_merge", args: "p_organization_id uuid, p_winner_id uuid, p_loser_id uuid, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
417
502
|
{ name: "migrate_promote", args: "p_organization_id uuid, p_table_id uuid, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
418
503
|
{ name: "migrate_purge", args: "p_organization_id uuid, p_table_id uuid DEFAULT NULL::uuid, p_dry_run boolean DEFAULT true", returns: "jsonb", security: "definer" },
|
|
504
|
+
{ name: "migrate_reclass", args: "p_organization_id uuid, p_id uuid, p_to text DEFAULT 'field'::text, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
419
505
|
{ name: "migrate_rename", args: "p_organization_id uuid, p_id uuid, p_to text, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
420
506
|
{ name: "migrate_reparent", args: "p_organization_id uuid, p_id uuid, p_parent_id uuid, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
421
507
|
{ name: "migrate_retype", args: "p_organization_id uuid, p_id uuid, p_to text, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
@@ -435,6 +521,20 @@ var STORE_DOORS = [
|
|
|
435
521
|
{ name: "parity_values", args: "p_organization_id uuid, p_record_id uuid", returns: "TABLE(field_key text, field_id uuid, parity_type text, behavior text, unit text, format text, value jsonb, value_version integer, actor text, written_at timestamp with time zone)", security: "invoker" },
|
|
436
522
|
{ name: "per_value_access_words", args: "", returns: "text[]", security: "invoker" },
|
|
437
523
|
{ name: "person_kernel_id", args: "", returns: "uuid", security: "invoker" },
|
|
524
|
+
{ name: "portal_admits", args: "p_organization_id uuid, p_user_id uuid DEFAULT NULL::uuid", returns: "boolean", security: "definer" },
|
|
525
|
+
{ name: "portal_card", args: "p_organization_id uuid, p_portal_id uuid", returns: "jsonb", security: "definer" },
|
|
526
|
+
{ name: "portal_declare", args: "p_organization_id uuid, p_title text, p_client_table_id uuid, p_tables jsonb, p_portal_id uuid DEFAULT NULL::uuid, p_slug text DEFAULT NULL::text, p_sign_in_method text DEFAULT 'magic_link'::text", returns: "uuid", security: "definer" },
|
|
527
|
+
{ name: "portal_field_map", args: "p_organization_id uuid, p_table_id uuid", returns: "TABLE(field_id uuid, field_key text, field_type text, points_at uuid)", security: "definer" },
|
|
528
|
+
{ name: "portal_invitation", args: "p_slug text, p_email text", returns: "jsonb", security: "definer" },
|
|
529
|
+
{ name: "portal_invite", args: "p_organization_id uuid, p_portal_id uuid, p_client_record_id uuid, p_email text, p_user_id uuid DEFAULT NULL::uuid", returns: "jsonb", security: "definer" },
|
|
530
|
+
{ name: "portal_me", args: "", returns: "jsonb", security: "definer" },
|
|
531
|
+
{ name: "portal_preview", args: "p_organization_id uuid, p_portal_id uuid, p_principal_id uuid, p_table_id uuid", returns: "TABLE(record_id uuid, title text)", security: "definer" },
|
|
532
|
+
{ name: "portal_principal_bind", args: "p_organization_id uuid, p_principal_id uuid, p_user_id uuid", returns: "jsonb", security: "definer" },
|
|
533
|
+
{ name: "portal_public", args: "p_slug text", returns: "jsonb", security: "definer" },
|
|
534
|
+
{ name: "portal_record_title", args: "p_organization_id uuid, p_record_id uuid", returns: "text", security: "definer" },
|
|
535
|
+
{ name: "portal_revoke", args: "p_organization_id uuid, p_portal_id uuid, p_principal_id uuid", returns: "jsonb", security: "definer" },
|
|
536
|
+
{ name: "portal_slug", args: "p_organization_id uuid, p_title text, p_portal_id uuid DEFAULT NULL::uuid", returns: "text", security: "definer" },
|
|
537
|
+
{ name: "portals", args: "p_organization_id uuid", returns: "TABLE(portal_id uuid, title text, slug text, client_table_id uuid, client_table text, is_active boolean, tables integer, invited integer, signed_in integer, sign_in_method text, opened_at timestamp with time zone)", security: "definer" },
|
|
438
538
|
{ name: "presentation_kernel_id", args: "", returns: "uuid", security: "invoker" },
|
|
439
539
|
{ name: "promote_field", args: "p_organization_id uuid, p_table_id uuid, p_field_id uuid", returns: "jsonb", security: "invoker" },
|
|
440
540
|
{ name: "promote_table", args: "p_organization_id uuid, p_table_id uuid", returns: "jsonb", security: "definer" },
|
|
@@ -485,10 +585,12 @@ var STORE_DOORS = [
|
|
|
485
585
|
{ name: "record_resolve", args: "p_organization_id uuid, p_id uuid", returns: "jsonb", security: "definer" },
|
|
486
586
|
{ name: "record_restore", args: "p_organization_id uuid, p_record_id uuid", returns: "void", security: "definer" },
|
|
487
587
|
{ name: "record_state_as_of", args: "p_record_id uuid, p_at timestamp with time zone", returns: "TABLE(state jsonb, replayed boolean)", security: "definer" },
|
|
588
|
+
{ name: "record_table", args: "p_organization_id uuid, p_record_id uuid", returns: "uuid", security: "definer" },
|
|
488
589
|
{ name: "record_update", args: "p_organization_id uuid, p_record_id uuid, p_patch jsonb, p_expected_version integer DEFAULT NULL::integer", returns: "integer", security: "definer" },
|
|
489
590
|
{ name: "record_values", args: "p_organization_id uuid, p_record_id uuid", returns: "jsonb", security: "invoker" },
|
|
490
591
|
{ name: "record_values_versioned", args: "p_organization_id uuid, p_record_id uuid", returns: "TABLE(field_key text, field_id uuid, value jsonb, value_version integer, source jsonb, absent_reason text, actor text, on_behalf_of text, written_at timestamp with time zone, alternates jsonb)", security: "definer" },
|
|
491
592
|
{ name: "record_write", args: "p_organization_id uuid, p_table_id uuid, p_data jsonb", returns: "uuid", security: "definer" },
|
|
593
|
+
{ name: "refusals_claiming_a_level_never_asked", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
|
|
492
594
|
{ name: "relation_carry", args: "p_organization_id uuid, p_container_id uuid, p_item_id uuid", returns: "uuid", security: "definer" },
|
|
493
595
|
{ name: "relation_edges_withdraw", args: "p_organization_id uuid, p_field_ids uuid[], p_why text", returns: "integer", security: "definer" },
|
|
494
596
|
{ name: "relation_own", args: "p_organization_id uuid, p_owner_id uuid, p_target_id uuid", returns: "uuid", security: "definer" },
|
|
@@ -534,7 +636,10 @@ var STORE_DOORS = [
|
|
|
534
636
|
{ name: "stamp_value_envelopes", args: "p_data jsonb, p_actor text, p_on_behalf_of text, p_at timestamp with time zone", returns: "jsonb", security: "invoker" },
|
|
535
637
|
{ name: "storage_modes", args: "", returns: "text[]", security: "invoker" },
|
|
536
638
|
{ name: "store_is_open", args: "p_organization_id uuid DEFAULT NULL::uuid", returns: "boolean", security: "invoker" },
|
|
639
|
+
{ name: "subscription_mute", args: "p_organization_id uuid, p_rule_id uuid, p_muted boolean DEFAULT true", returns: "boolean", security: "definer" },
|
|
640
|
+
{ name: "subscriptions", args: "p_organization_id uuid, p_table_id uuid DEFAULT NULL::uuid", returns: "TABLE(rule_id uuid, name text, table_id uuid, saved_view_id uuid, cadence text, schedule text, channel text, recipient_user_id uuid, event_key text, muted boolean, mine boolean, i_may_mute boolean)", security: "definer" },
|
|
537
641
|
{ name: "table_capacity", args: "p_organization_id uuid, p_table_id uuid", returns: "jsonb", security: "definer" },
|
|
642
|
+
{ name: "table_carries_its_rows", args: "p_user_id uuid, p_table_id uuid, p_required permission_level DEFAULT 'viewer'::permission_level", returns: "boolean", security: "definer" },
|
|
538
643
|
{ name: "table_contents", args: "p_organization_id uuid, p_table_id uuid", returns: "TABLE(record_id uuid, kind text, goes_at integer)", security: "invoker" },
|
|
539
644
|
{ name: "table_declare", args: "p_organization_id uuid, p_spec jsonb", returns: "uuid", security: "definer" },
|
|
540
645
|
{ name: "table_has_a_visible_record", args: "p_user uuid, p_organization_id uuid, p_table_id uuid", returns: "boolean", security: "definer" },
|
|
@@ -568,6 +673,7 @@ var STORE_DOORS = [
|
|
|
568
673
|
{ name: "widget_kernel_id", args: "", returns: "uuid", security: "invoker" },
|
|
569
674
|
{ name: "work_approval_approvers", args: "p_organization_id uuid, p_subject_id uuid, p_approver_id uuid DEFAULT NULL::uuid", returns: "TABLE(user_id uuid, name text, why text)", security: "definer" },
|
|
570
675
|
{ name: "work_approval_decide", args: "p_organization_id uuid, p_approval_id uuid, p_approve boolean, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
676
|
+
{ name: "work_approval_kinds", args: "", returns: "text[]", security: "invoker" },
|
|
571
677
|
{ name: "work_approval_may_decide", args: "p_organization_id uuid, p_approval_id uuid", returns: "boolean", security: "definer" },
|
|
572
678
|
{ name: "work_approval_read", args: "p_organization_id uuid, p_approval_id uuid", returns: "jsonb", security: "definer" },
|
|
573
679
|
{ name: "work_approval_request", args: "p_organization_id uuid, p_subject_id uuid, p_change jsonb, p_note text DEFAULT NULL::text, p_approver_id uuid DEFAULT NULL::uuid, p_origin text DEFAULT 'person'::text, p_conversation_id uuid DEFAULT NULL::uuid", returns: "jsonb", security: "definer" },
|
|
@@ -587,6 +693,7 @@ var STORE_DOORS = [
|
|
|
587
693
|
{ name: "work_slot_index_name", args: "p_table_id uuid", returns: "text", security: "invoker" },
|
|
588
694
|
{ name: "work_slot_release", args: "p_organization_id uuid, p_hold_id uuid", returns: "boolean", security: "definer" },
|
|
589
695
|
{ name: "work_slots_declare", args: "p_organization_id uuid, p_name text, p_slug text, p_home_id uuid DEFAULT NULL::uuid", returns: "jsonb", security: "definer" },
|
|
696
|
+
{ name: "work_state_id", args: "p_organization_id uuid, p_table_id uuid, p_value text", returns: "uuid", security: "invoker" },
|
|
590
697
|
{ name: "work_states", args: "", returns: "TABLE(sort integer, name text, terminal boolean, next text[])", security: "invoker" },
|
|
591
698
|
{ name: "work_take_assignment", args: "p_organization_id uuid, p_table_id uuid", returns: "jsonb", security: "definer" },
|
|
592
699
|
{ name: "work_template_declare", args: "p_organization_id uuid, p_name text, p_graph jsonb", returns: "uuid", security: "definer" },
|
|
@@ -635,17 +742,18 @@ var STORE_KNOBS = [
|
|
|
635
742
|
{ key: "world_publish_enabled", value: "false", type: "boolean" }
|
|
636
743
|
];
|
|
637
744
|
var STORE_REFUSAL_CODES = [
|
|
638
|
-
{ code: "02000", raised_by: "doc_render_body,doc_render_document,doc_render_read,doc_sign,doc_signature_intact,doc_signature_read,doc_template_read,doc_template_save,entity_field_retire,entity_field_update,entity_record_read,entity_value_write,external_history_event,external_rows,external_stub_upsert,external_writes_set,migrate_delete,migrate_extract_parent,migrate_merge,migrate_rename,migrate_reparent,migrate_retype,migrate_split,migrate_undo,organization_clear,read_record,record_delete,record_restore,record_update,relation_uncarry,share_access,share_grant,share_lane_set,share_people,share_revoke,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_assign,work_record_states,work_set_state" },
|
|
639
|
-
{ code: "0A000", raised_by: "external_rows,external_source_declare,external_write_through,promote_field,promoted_index_expr,promoted_query_sql,promoted_read,rule_eval,work_assign
|
|
640
|
-
{ code: "22004", raised_by: "_entity_custom_fields_guard,_value_envelope,actor_word,agg_assert_key,agg_sql,anon_capture,anon_token_issue,anon_write,assert_client_may_reach,doc_render_write,doc_sign,doc_signature_write,doc_template_save,external_history_event,external_rows,external_source_declare,external_stub_upsert,external_write_through,external_writes_set,form_declare,form_submit,home_add,io_comment_write,io_import_open,io_outbox_drain,io_restore,migrate_purge,migrate_split,migrate_undo,organization_clear,organization_contents,query_across_homes,query_by_coordinates,query_rollup,record_delete,record_reparent,record_resolve,record_restore,record_update,record_write,relation_carry,relation_own,rule_declare,share_grant,table_declare,work_approval_decide,work_approval_request,work_template_declare" },
|
|
745
|
+
{ code: "02000", raised_by: "dashboard_delete,dashboard_run,doc_render_body,doc_render_document,doc_render_read,doc_sign,doc_signature_intact,doc_signature_read,doc_template_read,doc_template_save,entity_field_retire,entity_field_update,entity_record_read,entity_value_write,external_history_event,external_rows,external_stub_upsert,external_writes_set,migrate_delete,migrate_extract_parent,migrate_merge,migrate_reclass,migrate_rename,migrate_reparent,migrate_retype,migrate_split,migrate_undo,organization_clear,portal_card,portal_declare,portal_invite,portal_preview,portal_principal_bind,portal_revoke,read_record,record_delete,record_restore,record_table,record_update,relation_uncarry,share_access,share_grant,share_lane_set,share_people,share_revoke,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_assign,work_record_states,work_set_state" },
|
|
746
|
+
{ code: "0A000", raised_by: "external_rows,external_source_declare,external_write_through,promote_field,promoted_index_expr,promoted_query_sql,promoted_read,rule_eval,work_assign" },
|
|
747
|
+
{ code: "22004", raised_by: "_entity_custom_fields_guard,_value_envelope,actor_word,agg_assert_key,agg_sql,anon_capture,anon_token_issue,anon_write,assert_client_may_reach,dashboard_block_normalize,dashboard_declare,dashboard_window_sql,doc_render_write,doc_sign,doc_signature_write,doc_template_save,external_history_event,external_rows,external_source_declare,external_stub_upsert,external_write_through,external_writes_set,form_declare,form_submit,home_add,io_comment_write,io_import_open,io_outbox_drain,io_restore,migrate_choice_keys,migrate_purge,migrate_reclass,migrate_split,migrate_undo,organization_clear,organization_contents,portal_declare,portal_invite,portal_principal_bind,query_across_homes,query_by_coordinates,query_rollup,record_delete,record_reparent,record_resolve,record_restore,record_update,record_write,relation_carry,relation_own,rule_declare,share_grant,table_declare,work_approval_decide,work_approval_request,work_template_declare" },
|
|
748
|
+
{ code: "22007", raised_by: "dashboard_window_sql" },
|
|
641
749
|
{ code: "22012", raised_by: "rule_eval" },
|
|
642
|
-
{ code: "22023", raised_by: "_entity_custom_fields_guard,_value_envelope,_work_shape_guard,actor_word,agg_assert_key,agg_sql,anon_token_issue,containment_parent,doc_render_body,doc_render_write,doc_signature_write,entity_value_write,external_history_event,external_source_declare,external_stub_upsert,external_write_through,io_import_open,io_proposal_accept,migrate_merge,my_levels,organization_clear,query_by_coordinates,query_rollup,record_update,relation_carry,rule_eval,rule_members,share_grant,share_lane_set,table_rules,visibility_as_of,work_approval_request,work_list,work_slot_hold" },
|
|
643
|
-
{ code: "23503", raised_by: "_containment_guard,_field_document_for,_record_rule_uses,anon_publish,anon_rate_take,anon_token_issue,anon_write,assert_organization_wall,delete_rule,doc_sign,doc_template_save,form_declare,form_submit,home_add,io_comment_write,io_import_rows,io_proposal_accept,migrate_demote,migrate_promote,promote_field,promote_table,record_applicability,record_reparent,relation_carry,relation_own,resolve_first_match,rule_applies,rule_declare,rule_eval,rule_members,rule_run,work_set_state,work_take_assignment,work_template_instantiate" },
|
|
750
|
+
{ code: "22023", raised_by: "_entity_custom_fields_guard,_value_envelope,_work_shape_guard,actor_word,agg_assert_key,agg_sql,anon_token_issue,containment_parent,dashboard_block_normalize,dashboard_window_sql,doc_render_body,doc_render_write,doc_signature_write,entity_value_write,external_history_event,external_source_declare,external_stub_upsert,external_write_through,io_import_open,io_proposal_accept,migrate_merge,migrate_reclass,my_levels,organization_clear,portal_declare,query_by_coordinates,query_rollup,record_update,relation_carry,rule_eval,rule_members,share_grant,share_lane_set,table_rules,visibility_as_of,work_approval_request,work_list,work_slot_hold" },
|
|
751
|
+
{ code: "23503", raised_by: "_containment_guard,_field_document_for,_record_rule_uses,anon_publish,anon_rate_take,anon_token_issue,anon_write,assert_organization_wall,dashboard_declare,delete_rule,doc_sign,doc_template_save,form_declare,form_submit,home_add,io_comment_write,io_import_rows,io_proposal_accept,migrate_demote,migrate_promote,promote_field,promote_table,record_applicability,record_reparent,relation_carry,relation_own,resolve_first_match,rule_applies,rule_declare,rule_eval,rule_members,rule_run,subscription_mute,work_set_state,work_take_assignment,work_template_instantiate" },
|
|
644
752
|
{ code: "23505", raised_by: "_unique_rule_holds,doc_sign,doc_signature_write,entity_field_declare,field_declare,home_add,io_proposal_accept,relation_carry,relation_own,share_grant,work_approval_decide,work_slot_hold" },
|
|
645
|
-
{ code: "23514", raised_by: "_containment_guard,_dated_values_guard,_derived_fields,_entity_custom_fields_guard,_field_document_for,_field_shape_guard,_field_type_parity_guard,_merge_field_shape_guard,_merge_field_temporal_guard,_promoted_field_cap_guard,_record_rule_uses,_resolve_choice_words,_rule_shape_guard,_rule_topology_guard,_store_relation_edge_names_its_field,_table_shape_guard,_value_envelope,_work_shape_guard,_workdoors_approval_guard,assert_entity_is_organization_scoped,doc_sign,doc_signature_write,doc_template_save,entity_field_declare,entity_field_retire,entity_field_update,entity_records_find,entity_table,field_declare,field_retire,field_update,home_add,migrate_merge,relation_carry,relation_own,validate_value_envelope,validate_values,work_set_state,work_slots_declare,work_take_assignment,work_template_instantiate" },
|
|
753
|
+
{ code: "23514", raised_by: "_containment_guard,_dated_values_guard,_derived_fields,_entity_custom_fields_guard,_field_class_guard,_field_document_for,_field_shape_guard,_field_type_parity_guard,_merge_field_shape_guard,_merge_field_temporal_guard,_promoted_field_cap_guard,_record_rule_uses,_resolve_choice_words,_rule_shape_guard,_rule_topology_guard,_store_relation_edge_names_its_field,_table_shape_guard,_value_envelope,_work_shape_guard,_workdoors_approval_guard,assert_entity_is_organization_scoped,doc_sign,doc_signature_write,doc_template_save,entity_field_declare,entity_field_retire,entity_field_update,entity_records_find,entity_table,field_declare,field_retire,field_update,home_add,migrate_merge,relation_carry,relation_own,validate_value_envelope,validate_values,work_set_state,work_slots_declare,work_take_assignment,work_template_instantiate" },
|
|
646
754
|
{ code: "40001", raised_by: "has_visibility_at" },
|
|
647
|
-
{ code: "42501", raised_by: "_doc_render_immutable,_doc_signature_immutable,_field_definition_write,_field_write_door,_rule_definition_write,_store_door,anon_capture,anon_inbound_land,anon_publish,anon_token_issue,anon_token_verify,anon_write,assert_client_may_change,assert_client_may_open,assert_client_may_reach,assert_may_know_table,assert_organization_admin,assert_store_door,entity_field_declare,entity_field_retire,entity_field_update,entity_value_write,external_write_through,form_declare,form_submit,io_comment_resolve,io_comment_write,io_restore,migrate_purge,my_levels,organization_clear,promote_table,query_visibility_parity,read_record,read_records,share_grant,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_person" },
|
|
648
|
-
{ code: "42703", raised_by: "entity_table" },
|
|
755
|
+
{ code: "42501", raised_by: "_doc_render_immutable,_doc_signature_immutable,_field_definition_write,_field_write_door,_rule_definition_write,_store_door,anon_capture,anon_inbound_land,anon_publish,anon_token_issue,anon_token_verify,anon_write,assert_client_may_change,assert_client_may_open,assert_client_may_reach,assert_may_know_table,assert_organization_admin,assert_store_door,entity_field_declare,entity_field_retire,entity_field_update,entity_value_write,external_write_through,form_declare,form_submit,io_comment_resolve,io_comment_write,io_restore,migrate_purge,migrate_reclass,my_levels,organization_clear,portal_declare,portal_invitation,portal_invite,portal_principal_bind,promote_table,query_visibility_parity,read_record,read_records,share_grant,subscription_mute,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_person" },
|
|
756
|
+
{ code: "42703", raised_by: "entity_table,portal_declare" },
|
|
649
757
|
{ code: "53400", raised_by: "anon_rate_take,delete_cascade_closure,promote_field" },
|
|
650
758
|
{ code: "54001", raised_by: "record_delete" },
|
|
651
759
|
{ code: "PT409", raised_by: "record_update" }
|
|
@@ -1821,6 +1929,32 @@ var DOORS = {
|
|
|
1821
1929
|
// are server-lane doors and a browser never calls them.
|
|
1822
1930
|
forms: "forms",
|
|
1823
1931
|
formDeclare: "form_declare",
|
|
1932
|
+
// THE CLIENT PORTAL, OWNER'S SIDE (VIS-31 / PORTAL). A portal is how somebody
|
|
1933
|
+
// with NO membership is let in to see the records that name them. `portals`
|
|
1934
|
+
// lists them, `portalCard` opens one, `portalDeclare` states what it exposes,
|
|
1935
|
+
// `portalInvite` and `portalRevoke` are the two acts on a person, and
|
|
1936
|
+
// `portalPreview` is "view as this client" — it asks `custom.visible_set` for
|
|
1937
|
+
// HER user id, the same call `custom.read_records` makes when she opens the
|
|
1938
|
+
// page, so the preview cannot disagree with what she sees. The CLIENT-side
|
|
1939
|
+
// pair (`custom.portal_public`, `custom.portal_invitation`, `custom.portal_me`)
|
|
1940
|
+
// is deliberately absent here: those belong to the outsider's own shell.
|
|
1941
|
+
portals: "portals",
|
|
1942
|
+
portalCard: "portal_card",
|
|
1943
|
+
portalDeclare: "portal_declare",
|
|
1944
|
+
portalInvite: "portal_invite",
|
|
1945
|
+
portalRevoke: "portal_revoke",
|
|
1946
|
+
portalPreview: "portal_preview",
|
|
1947
|
+
// SCR-16 — the canvas. A dashboard is a record in the presentation kernel
|
|
1948
|
+
// whose blocks are saved SPECS for the eighth verb; `dashboardRun` walks them
|
|
1949
|
+
// under the CALLER'S principal, so nothing here is precomputed and nothing is
|
|
1950
|
+
// summed in a browser. `dashboardStuck` is the seventh block kind on its own,
|
|
1951
|
+
// because "what has not moved in fourteen days" is a question a screen asks
|
|
1952
|
+
// outside a canvas too.
|
|
1953
|
+
dashboards: "dashboards",
|
|
1954
|
+
dashboardDeclare: "dashboard_declare",
|
|
1955
|
+
dashboardRun: "dashboard_run",
|
|
1956
|
+
dashboardStuck: "dashboard_stuck",
|
|
1957
|
+
dashboardDelete: "dashboard_delete",
|
|
1824
1958
|
// The eighth verb (AGT-N-8): a grouped, bucketed, filtered count/sum/avg/
|
|
1825
1959
|
// min/max computed INSIDE the read door's own query, so a chart shows exactly
|
|
1826
1960
|
// the rows this person may see and never fetches the ones they may not.
|
|
@@ -1831,6 +1965,12 @@ var DOORS = {
|
|
|
1831
1965
|
// over a saved view. There is no subscription TABLE and no second notifier.
|
|
1832
1966
|
aggSubscriptions: "agg_subscriptions",
|
|
1833
1967
|
aggSubscriptionCadences: "agg_subscription_cadences",
|
|
1968
|
+
// The OWNER's side of DOOR-18. `agg_subscriptions` is the notifier's reader
|
|
1969
|
+
// and is not client-callable; these two are what a person reaches: what am I
|
|
1970
|
+
// being told about, and switch this one off. A form's notify Rule is one of
|
|
1971
|
+
// these rows, so "tell me when a patient arrives" can also be un-told.
|
|
1972
|
+
subscriptions: "subscriptions",
|
|
1973
|
+
subscriptionMute: "subscription_mute",
|
|
1834
1974
|
// The doc doors: a template is saved, a render is written once and frozen,
|
|
1835
1975
|
// and a signature is checked against the exact bytes that were signed.
|
|
1836
1976
|
docTemplateSave: "doc_template_save",
|
|
@@ -1935,6 +2075,14 @@ var BY_SQLSTATE = {
|
|
|
1935
2075
|
// caught it raised by a door this package did not know about — which is the
|
|
1936
2076
|
// suite working, and is why the map is a census rather than a guess.
|
|
1937
2077
|
"42703": "invalid_argument",
|
|
2078
|
+
// 22007 — a date or a time the store could not read as one. It is raised by
|
|
2079
|
+
// `custom.dashboard_window_sql`, which is handed a window a caller wrote
|
|
2080
|
+
// ("last 30 days", a literal date), so the class is again "the call named
|
|
2081
|
+
// something the shape does not accept" and the store's own sentence names the
|
|
2082
|
+
// text it could not read. Added 2026-09-20 (lane SCREEN-BREAK) after the
|
|
2083
|
+
// live-door census caught it — the same way 42703 arrived, which is the
|
|
2084
|
+
// census working rather than a guess.
|
|
2085
|
+
"22007": "invalid_argument",
|
|
1938
2086
|
"02000": "not_found",
|
|
1939
2087
|
"23503": "missing_reference",
|
|
1940
2088
|
"23505": "already_exists",
|
|
@@ -2304,9 +2452,11 @@ function createRecordsClient(config) {
|
|
|
2304
2452
|
);
|
|
2305
2453
|
if (!applicable.ok) return err(applicable.error);
|
|
2306
2454
|
const rows = applicable.data ?? [];
|
|
2307
|
-
|
|
2308
|
-
|
|
2455
|
+
const fields = rows.map((row) => ({ id: row.id, ...row.data }));
|
|
2456
|
+
fields.sort(
|
|
2457
|
+
(a, b) => (a.sort ?? 0) - (b.sort ?? 0) || (a.label ?? "").localeCompare(b.label ?? "")
|
|
2309
2458
|
);
|
|
2459
|
+
return ok(fields);
|
|
2310
2460
|
},
|
|
2311
2461
|
async fieldOptions({ field_id }) {
|
|
2312
2462
|
return callDoor(
|
|
@@ -2480,6 +2630,65 @@ function createRecordsClient(config) {
|
|
|
2480
2630
|
"formDeclare"
|
|
2481
2631
|
);
|
|
2482
2632
|
},
|
|
2633
|
+
async portals() {
|
|
2634
|
+
return callDoor(DOORS.portals, { p_organization_id: org }, "portals");
|
|
2635
|
+
},
|
|
2636
|
+
async portalCard({ portal_id }) {
|
|
2637
|
+
return callDoor(
|
|
2638
|
+
DOORS.portalCard,
|
|
2639
|
+
{ p_organization_id: org, p_portal_id: portal_id },
|
|
2640
|
+
"portalCard"
|
|
2641
|
+
);
|
|
2642
|
+
},
|
|
2643
|
+
async portalDeclare(args) {
|
|
2644
|
+
return callDoor(
|
|
2645
|
+
DOORS.portalDeclare,
|
|
2646
|
+
{
|
|
2647
|
+
p_organization_id: org,
|
|
2648
|
+
p_title: args.title,
|
|
2649
|
+
p_client_table_id: args.client_table_id,
|
|
2650
|
+
p_tables: args.tables,
|
|
2651
|
+
p_portal_id: args.portal_id ?? null,
|
|
2652
|
+
p_slug: args.slug ?? null,
|
|
2653
|
+
p_sign_in_method: args.sign_in_method ?? "magic_link"
|
|
2654
|
+
},
|
|
2655
|
+
"portalDeclare"
|
|
2656
|
+
);
|
|
2657
|
+
},
|
|
2658
|
+
async portalInvite(args) {
|
|
2659
|
+
return callDoor(
|
|
2660
|
+
DOORS.portalInvite,
|
|
2661
|
+
{
|
|
2662
|
+
p_organization_id: org,
|
|
2663
|
+
p_portal_id: args.portal_id,
|
|
2664
|
+
p_client_record_id: args.client_record_id,
|
|
2665
|
+
p_email: args.email,
|
|
2666
|
+
// ALWAYS null from a client. See the interface comment: an invitation
|
|
2667
|
+
// confers nothing until the person follows their own sign-in link.
|
|
2668
|
+
p_user_id: null
|
|
2669
|
+
},
|
|
2670
|
+
"portalInvite"
|
|
2671
|
+
);
|
|
2672
|
+
},
|
|
2673
|
+
async portalRevoke({ portal_id, principal_id }) {
|
|
2674
|
+
return callDoor(
|
|
2675
|
+
DOORS.portalRevoke,
|
|
2676
|
+
{ p_organization_id: org, p_portal_id: portal_id, p_principal_id: principal_id },
|
|
2677
|
+
"portalRevoke"
|
|
2678
|
+
);
|
|
2679
|
+
},
|
|
2680
|
+
async portalPreview({ portal_id, principal_id, table_id }) {
|
|
2681
|
+
return callDoor(
|
|
2682
|
+
DOORS.portalPreview,
|
|
2683
|
+
{
|
|
2684
|
+
p_organization_id: org,
|
|
2685
|
+
p_portal_id: portal_id,
|
|
2686
|
+
p_principal_id: principal_id,
|
|
2687
|
+
p_table_id: table_id
|
|
2688
|
+
},
|
|
2689
|
+
"portalPreview"
|
|
2690
|
+
);
|
|
2691
|
+
},
|
|
2483
2692
|
async ruleRun({ rule_id, values, context }) {
|
|
2484
2693
|
return callDoor(
|
|
2485
2694
|
DOORS.ruleRun,
|
|
@@ -2504,6 +2713,55 @@ function createRecordsClient(config) {
|
|
|
2504
2713
|
"ruleEval"
|
|
2505
2714
|
);
|
|
2506
2715
|
},
|
|
2716
|
+
async dashboards(args) {
|
|
2717
|
+
return callDoor(
|
|
2718
|
+
DOORS.dashboards,
|
|
2719
|
+
{ p_organization_id: org, p_table_id: args?.table_id ?? null },
|
|
2720
|
+
"dashboards"
|
|
2721
|
+
);
|
|
2722
|
+
},
|
|
2723
|
+
async dashboardDeclare(args) {
|
|
2724
|
+
return callDoor(
|
|
2725
|
+
DOORS.dashboardDeclare,
|
|
2726
|
+
{
|
|
2727
|
+
p_organization_id: org,
|
|
2728
|
+
p_table_id: args.table_id,
|
|
2729
|
+
p_name: args.name,
|
|
2730
|
+
p_blocks: args.blocks ?? [],
|
|
2731
|
+
p_presentation: args.presentation ?? {},
|
|
2732
|
+
p_dashboard_id: args.dashboard_id ?? null
|
|
2733
|
+
},
|
|
2734
|
+
"dashboardDeclare"
|
|
2735
|
+
);
|
|
2736
|
+
},
|
|
2737
|
+
async dashboardRun({ dashboard_id, filter }) {
|
|
2738
|
+
return callDoor(
|
|
2739
|
+
DOORS.dashboardRun,
|
|
2740
|
+
{ p_organization_id: org, p_dashboard_id: dashboard_id, p_filter: filter ?? {} },
|
|
2741
|
+
"dashboardRun"
|
|
2742
|
+
);
|
|
2743
|
+
},
|
|
2744
|
+
async dashboardStuck({ table_id, state_key, days, filter, limit }) {
|
|
2745
|
+
return callDoor(
|
|
2746
|
+
DOORS.dashboardStuck,
|
|
2747
|
+
{
|
|
2748
|
+
p_organization_id: org,
|
|
2749
|
+
p_table_id: table_id,
|
|
2750
|
+
p_state_key: state_key,
|
|
2751
|
+
p_days: days ?? 14,
|
|
2752
|
+
p_filter: filter ?? {},
|
|
2753
|
+
p_limit: limit ?? 50
|
|
2754
|
+
},
|
|
2755
|
+
"dashboardStuck"
|
|
2756
|
+
);
|
|
2757
|
+
},
|
|
2758
|
+
async dashboardDelete({ dashboard_id }) {
|
|
2759
|
+
return callDoor(
|
|
2760
|
+
DOORS.dashboardDelete,
|
|
2761
|
+
{ p_organization_id: org, p_dashboard_id: dashboard_id },
|
|
2762
|
+
"dashboardDelete"
|
|
2763
|
+
);
|
|
2764
|
+
},
|
|
2507
2765
|
async recordAggregate({ table_id, groupBy, measures, bucket, filter, limit }) {
|
|
2508
2766
|
return callDoor(
|
|
2509
2767
|
DOORS.recordAggregate,
|
|
@@ -2539,6 +2797,20 @@ function createRecordsClient(config) {
|
|
|
2539
2797
|
async aggSubscriptionCadences() {
|
|
2540
2798
|
return callDoor(DOORS.aggSubscriptionCadences, {}, "aggSubscriptionCadences");
|
|
2541
2799
|
},
|
|
2800
|
+
async subscriptions(args) {
|
|
2801
|
+
return callDoor(
|
|
2802
|
+
DOORS.subscriptions,
|
|
2803
|
+
{ p_organization_id: org, p_table_id: args?.table_id ?? null },
|
|
2804
|
+
"subscriptions"
|
|
2805
|
+
);
|
|
2806
|
+
},
|
|
2807
|
+
async subscriptionMute({ rule_id, muted }) {
|
|
2808
|
+
return callDoor(
|
|
2809
|
+
DOORS.subscriptionMute,
|
|
2810
|
+
{ p_organization_id: org, p_rule_id: rule_id, p_muted: muted },
|
|
2811
|
+
"subscriptionMute"
|
|
2812
|
+
);
|
|
2813
|
+
},
|
|
2542
2814
|
async docTemplateSave({ table_id, name, body, template_id }) {
|
|
2543
2815
|
return callDoor(
|
|
2544
2816
|
DOORS.docTemplateSave,
|
|
@@ -3142,7 +3414,7 @@ function pgJsonbText(value) {
|
|
|
3142
3414
|
return JSON.stringify(value);
|
|
3143
3415
|
}
|
|
3144
3416
|
var jsonBytes = (value) => new TextEncoder().encode(pgJsonbText(value)).length;
|
|
3145
|
-
var
|
|
3417
|
+
var UUID2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
3146
3418
|
function labelOf(field) {
|
|
3147
3419
|
return field.label && field.label.length > 0 ? field.label : field.key;
|
|
3148
3420
|
}
|
|
@@ -3252,7 +3524,7 @@ function predictValueRefusals(fields, values, recordType) {
|
|
|
3252
3524
|
message: `${label} takes one of its choices, and it was given a ${jsonType(item)}`,
|
|
3253
3525
|
hint: "FLD-5 / FLD-6: a list field stores the id of the option RECORD, because every pick-list is already a Table."
|
|
3254
3526
|
});
|
|
3255
|
-
} else if (!
|
|
3527
|
+
} else if (!UUID2.test(item)) {
|
|
3256
3528
|
found.push({
|
|
3257
3529
|
...base,
|
|
3258
3530
|
message: `${label} was given a choice that is not one of its choices`,
|
|
@@ -3262,7 +3534,7 @@ function predictValueRefusals(fields, values, recordType) {
|
|
|
3262
3534
|
} else if (field.type === "relation") {
|
|
3263
3535
|
if (typeof item !== "string") {
|
|
3264
3536
|
found.push({ ...base, message: `${label} points at a record, and it was given a ${jsonType(item)}`, hint: "FLD-1: relation." });
|
|
3265
|
-
} else if (!
|
|
3537
|
+
} else if (!UUID2.test(item)) {
|
|
3266
3538
|
found.push({
|
|
3267
3539
|
...base,
|
|
3268
3540
|
message: `${label} points at something that is not there`,
|