@ai-matrx/records 0.98.7 → 0.98.9
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 +12 -0
- package/dist/{table-kind-CboiMJuE.d.cts → client-9fzhCPD5.d.cts} +2771 -4
- package/dist/{table-kind-B4sdlvHf.d.ts → client-DcWZjmg2.d.ts} +2771 -4
- package/dist/core/index.cjs +154 -3
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +109 -18
- package/dist/core/index.d.ts +109 -18
- package/dist/core/index.js +154 -3
- package/dist/core/index.js.map +1 -1
- package/dist/data/index.cjs +52 -0
- package/dist/data/index.cjs.map +1 -1
- package/dist/data/index.d.cts +11 -12
- package/dist/data/index.d.ts +11 -12
- package/dist/data/index.js +52 -0
- package/dist/data/index.js.map +1 -1
- package/dist/{declareTable-BIuPJ3Vj.d.ts → declareTable-B6ic3leL.d.ts} +3 -4
- package/dist/{declareTable-d-HxRmF0.d.cts → declareTable-_GwN-ERY.d.cts} +3 -4
- package/dist/{doors-Bx3Shs3z.d.cts → doors-Dm5q9H8Y.d.cts} +1 -1
- package/dist/{doors-BTifsjNv.d.ts → doors-t-Oc2l9E.d.ts} +1 -1
- package/dist/entity/index.d.cts +7 -7
- package/dist/entity/index.d.ts +7 -7
- package/dist/{field-CJtssH3q.d.ts → field-BIRNApm1.d.ts} +2 -2
- package/dist/{field-DoVl2I9K.d.cts → field-BLy8drjM.d.cts} +2 -2
- package/dist/forms/index.d.cts +3 -3
- package/dist/forms/index.d.ts +3 -3
- package/dist/index.cjs +45 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -13
- package/dist/index.d.ts +30 -13
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -1
- package/dist/memory/index.d.cts +7 -7
- package/dist/memory/index.d.ts +7 -7
- package/dist/{objectOrganization-Crk9gJUM.d.ts → objectOrganization-D5Ytjah7.d.ts} +1 -1
- package/dist/{objectOrganization-CUa6jjhV.d.cts → objectOrganization-zgpoUAH1.d.cts} +1 -1
- package/dist/{port-CRP5g9l9.d.cts → port-B9glCG2h.d.cts} +3 -3
- package/dist/{port-CtnELAJQ.d.ts → port-C-p-_lAu.d.ts} +3 -3
- package/dist/{portal-DW5NGBT0.d.ts → portal-B9HCNPTc.d.ts} +2 -2
- package/dist/{portal-C4N9ByaY.d.cts → portal-C_LgvDeh.d.cts} +2 -2
- package/dist/{ports-WwHHNwge.d.ts → ports-BE_5jz-c.d.ts} +2 -2
- package/dist/{ports-YIh9jrCZ.d.cts → ports-BIdYUS-C.d.cts} +2 -2
- package/dist/questions/index.d.cts +9 -10
- package/dist/questions/index.d.ts +9 -10
- package/dist/react/index.cjs +97 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +86 -1
- package/dist/react/index.d.ts +86 -1
- package/dist/react/index.js +97 -0
- package/dist/react/index.js.map +1 -1
- package/dist/realtime/index.d.cts +3 -3
- package/dist/realtime/index.d.ts +3 -3
- package/dist/{record-CxGK1OEK.d.cts → record-BrJNCmH1.d.cts} +1 -1
- package/dist/{record-CxGK1OEK.d.ts → record-BrJNCmH1.d.ts} +1 -1
- package/dist/{relation-Dh-lCkkh.d.ts → relation-BxGXLRaG.d.ts} +3 -3
- package/dist/{relation-DSGhM3tO.d.cts → relation-R10qQyQU.d.cts} +3 -3
- package/dist/{rule-DQpC7WqT.d.cts → rule-BGtYd6Pf.d.cts} +2 -2
- package/dist/{rule-xNwJF6Qo.d.ts → rule-BtjrE42J.d.ts} +2 -2
- package/dist/scopes/index.d.cts +3 -3
- package/dist/scopes/index.d.ts +3 -3
- package/dist/search/index.d.cts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/setup/index.cjs +52 -0
- package/dist/setup/index.cjs.map +1 -1
- package/dist/setup/index.d.cts +12 -13
- package/dist/setup/index.d.ts +12 -13
- package/dist/setup/index.js +52 -0
- package/dist/setup/index.js.map +1 -1
- package/dist/{subscription-BVCn1PVe.d.cts → subscription-BEM4B4dR.d.cts} +3 -3
- package/dist/{subscription-DQzPVKBR.d.ts → subscription-Ca15Z7Gu.d.ts} +3 -3
- package/dist/templates/index.d.cts +10 -10
- package/dist/templates/index.d.ts +10 -10
- package/dist/typed-table/index.cjs +52 -0
- package/dist/typed-table/index.cjs.map +1 -1
- package/dist/typed-table/index.d.cts +10 -11
- package/dist/typed-table/index.d.ts +10 -11
- package/dist/typed-table/index.js +52 -0
- package/dist/typed-table/index.js.map +1 -1
- package/dist/{types-3lM5f6b0.d.cts → types-5ql9_q-o.d.cts} +2 -2
- package/dist/{types-04kFNi3-.d.ts → types-BALEbMc8.d.ts} +2 -2
- package/dist/{types-DKJO83lQ.d.cts → types-BhnjvJ8U.d.cts} +2 -2
- package/dist/{types-SUAmeBId.d.ts → types-CURw95qc.d.ts} +2 -2
- package/dist/{types-DKeGkHpE.d.cts → types-DRMeL0uW.d.cts} +2 -2
- package/dist/{types-DJVccwh0.d.ts → types-_odOqLOe.d.ts} +2 -2
- package/dist/use-cases/index.d.cts +5 -5
- package/dist/use-cases/index.d.ts +5 -5
- package/dist/{validate-BIJtP2KB.d.cts → validate-Cdtk0y18.d.cts} +1 -1
- package/dist/{validate--y-pPc-c.d.ts → validate-ChibJPPI.d.ts} +1 -1
- package/dist/views/index.d.cts +9 -10
- package/dist/views/index.d.ts +9 -10
- package/package.json +2 -2
- package/dist/client-C1B-MNzb.d.ts +0 -2704
- package/dist/client-D2jAgJNn.d.cts +0 -2704
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { U as Uuid, h as Timestamp,
|
|
2
|
-
import {
|
|
3
|
-
import { g as
|
|
1
|
+
import { U as Uuid, h as Timestamp, l as ReadRow, n as RecordDocument, T as TableType, b as TableDisplay, S as StorageMode, av as TableOrigin, ar as StoredRecord, p as ParityFieldType, a as RecordsError, m as RecordsErrorCode, R as RecordsResult, ad as RecordChange, ae as RecordChangeResult, af as RecordGraphWritten, ai as RecordRead, k as RecordPageSort, ah as RecordPage, ag as RecordKeysetPage, aj as RecordRevision, s as ReadValue, aD as WriteConflict } from './record-BrJNCmH1.cjs';
|
|
2
|
+
import { B as StoreFilter, o as DashboardSummary, l as DashboardBlock, R as RecordFilter, e as AggregateCompare, A as AggregateBucket, n as DashboardRunResult, C as StuckRow, c as AggregateMeasure, j as AggregateRow, E as Subscription, M as MySubscription, G as SubscriptionSpec, u as DigestPreview, d as SavedViewRow, z as SavedViewSpecIn, v as RowTemplateRow } from './subscription-BEM4B4dR.cjs';
|
|
3
|
+
import { f as RelationCoordinate, j as RelationWordsManyArgs, g as RelationIcons, k as ReverseColumn, o as ReverseLinksManyArgs, m as ReverseLinks, n as ReverseLinksFieldsArgs, S as SourceArchived } from './relation-R10qQyQU.cjs';
|
|
4
|
+
import { F as Field, r as FieldPatch, N as NewFieldDeclaration, z as RelationNamesAnswer, o as FieldDuplicated, s as FieldProposal, T as TableProposal, h as ButtonPressed } from './field-BLy8drjM.cjs';
|
|
5
|
+
import { s as ScopeDoors } from './doors-Dm5q9H8Y.cjs';
|
|
6
|
+
import { F as FormSummary, b as BookingSummary, B as BookingAvailability, a as BookingDeclared, e as FormRoute, d as FormResults } from './rule-BGtYd6Pf.cjs';
|
|
7
|
+
import { g as PermissionLevel, a as RecordsConfig, M as MyLevel } from './ports-BIdYUS-C.cjs';
|
|
8
|
+
import { F as FormLookOptions, t as PortalSummary, d as PortalArchiveFilter, c as PortalArchiveAnswer, v as PortalTableRef, e as PortalCard, g as PortalConfigInput, l as PortalFormSpec, i as PortalFormAnswer, m as PortalInvitation, p as PortalRevocation, n as PortalPreviewRow } from './portal-C_LgvDeh.cjs';
|
|
4
9
|
|
|
5
10
|
/**
|
|
6
11
|
* THE TWO LANES THE ARCHIVED-ITEMS LAW NAMES (Arman, 2026-09-09) — the same
|
|
@@ -540,6 +545,36 @@ interface RecordsMerged {
|
|
|
540
545
|
resolves_to?: string | null;
|
|
541
546
|
at?: string;
|
|
542
547
|
}
|
|
548
|
+
/** `custom.migrate_split`'s answer. The original keeps its id; the moved values live on `new_record`. */
|
|
549
|
+
interface RecordSplit {
|
|
550
|
+
verb: "split";
|
|
551
|
+
kept_the_id: string;
|
|
552
|
+
new_record: string;
|
|
553
|
+
migration_id: string;
|
|
554
|
+
moved: string[];
|
|
555
|
+
old_id_resolves_to?: string | null;
|
|
556
|
+
at?: string;
|
|
557
|
+
}
|
|
558
|
+
/** `custom.migrate_extract_parent`'s answer. The named values were COPIED up into `parent`, and the record now sits under it. */
|
|
559
|
+
interface ParentExtracted {
|
|
560
|
+
verb: "extract_parent";
|
|
561
|
+
record_id: string;
|
|
562
|
+
parent: string;
|
|
563
|
+
was_under: string | null;
|
|
564
|
+
migration_id: string;
|
|
565
|
+
at?: string;
|
|
566
|
+
}
|
|
567
|
+
/** One row of `custom.migrations`: a recorded Migration on one target, and whether it was put back. */
|
|
568
|
+
interface MigrationEntry {
|
|
569
|
+
id: string;
|
|
570
|
+
verb: string;
|
|
571
|
+
target_kind: string;
|
|
572
|
+
target_id: string;
|
|
573
|
+
note: string | null;
|
|
574
|
+
applied_at: string;
|
|
575
|
+
applied_by: string | null;
|
|
576
|
+
undone_at: string | null;
|
|
577
|
+
}
|
|
543
578
|
/** `custom.migrate_undo`'s answer: the Migration it put back. */
|
|
544
579
|
interface MigrationUndone {
|
|
545
580
|
undone: string;
|
|
@@ -549,6 +584,8 @@ interface MigrationUndone {
|
|
|
549
584
|
version_after?: number | null;
|
|
550
585
|
also_restored?: number;
|
|
551
586
|
ids_unaliased?: number;
|
|
587
|
+
/** A split or an extracted parent: the record the Migration made, archived by the undo. */
|
|
588
|
+
removed?: string | null;
|
|
552
589
|
at?: string;
|
|
553
590
|
}
|
|
554
591
|
/**
|
|
@@ -3844,4 +3881,2734 @@ declare function tableJsonSchema(facts: TableKindFacts, mode: TableSchemaMode):
|
|
|
3844
3881
|
*/
|
|
3845
3882
|
declare function tableRenderSchema(facts: TableKindFacts): TableRenderSchema;
|
|
3846
3883
|
|
|
3847
|
-
|
|
3884
|
+
/**
|
|
3885
|
+
* DOOR-8. As-of on EITHER clock, and they are different questions:
|
|
3886
|
+
* · `record` — the record clock: what this record looked like at version time.
|
|
3887
|
+
* · `world` — the world clock: which values were true of the world then
|
|
3888
|
+
* (the Field's `dated` modifier).
|
|
3889
|
+
*/
|
|
3890
|
+
interface AsOf {
|
|
3891
|
+
clock: "record" | "world";
|
|
3892
|
+
at: Timestamp;
|
|
3893
|
+
}
|
|
3894
|
+
/** A predicate over a PROMOTED field (REC-5: promotion light -> heavy). */
|
|
3895
|
+
interface PromotedPredicate {
|
|
3896
|
+
field_key: string;
|
|
3897
|
+
/** The value as text, exactly as `custom.promoted_read` takes it. */
|
|
3898
|
+
equals: string;
|
|
3899
|
+
}
|
|
3900
|
+
interface RecordQuery {
|
|
3901
|
+
table_id: Uuid;
|
|
3902
|
+
/** DOOR-6. Any combination, any subset. An empty list means "no relation constraint". */
|
|
3903
|
+
relations?: RelationCoordinate[];
|
|
3904
|
+
/** Predicates the store can answer from an index. */
|
|
3905
|
+
promoted?: PromotedPredicate[];
|
|
3906
|
+
/** DOOR-8. */
|
|
3907
|
+
asOf?: AsOf;
|
|
3908
|
+
/** DOOR-9. Ask across EVERY Home of this Table in one answer. */
|
|
3909
|
+
acrossHomes?: boolean;
|
|
3910
|
+
/** REC-23. Soft-deleted rows are out unless you say otherwise. */
|
|
3911
|
+
includeDeleted?: boolean;
|
|
3912
|
+
/** FLD-10. */
|
|
3913
|
+
recordType?: string;
|
|
3914
|
+
orderBy?: {
|
|
3915
|
+
column: "created_at" | "updated_at";
|
|
3916
|
+
ascending?: boolean;
|
|
3917
|
+
};
|
|
3918
|
+
limit?: number;
|
|
3919
|
+
offset?: number;
|
|
3920
|
+
}
|
|
3921
|
+
/**
|
|
3922
|
+
* What a query decomposes into: a set of door calls whose answers INTERSECT,
|
|
3923
|
+
* then one filtered read. Kept as data rather than hidden inside the client so
|
|
3924
|
+
* the suite can assert the plan as well as the answer — a query that quietly
|
|
3925
|
+
* stopped applying one of its coordinates is otherwise invisible.
|
|
3926
|
+
*/
|
|
3927
|
+
interface QueryPlan {
|
|
3928
|
+
/** One `relation_targets` call per coordinate; the id sets are intersected. */
|
|
3929
|
+
relationCalls: Array<{
|
|
3930
|
+
door: "relation_targets";
|
|
3931
|
+
record_id: Uuid;
|
|
3932
|
+
via_key: string | null;
|
|
3933
|
+
}>;
|
|
3934
|
+
/** One `promoted_read` call per predicate; intersected with the above. */
|
|
3935
|
+
promotedCalls: Array<{
|
|
3936
|
+
door: "promoted_read";
|
|
3937
|
+
field_key: string;
|
|
3938
|
+
value: string;
|
|
3939
|
+
}>;
|
|
3940
|
+
/** The filtered read over `custom.record`, which the store's policies gate. */
|
|
3941
|
+
read: {
|
|
3942
|
+
table_id: Uuid;
|
|
3943
|
+
includeDeleted: boolean;
|
|
3944
|
+
recordType: string | null;
|
|
3945
|
+
asOf: AsOf | null;
|
|
3946
|
+
acrossHomes: boolean;
|
|
3947
|
+
orderBy: {
|
|
3948
|
+
column: string;
|
|
3949
|
+
ascending: boolean;
|
|
3950
|
+
};
|
|
3951
|
+
limit: number;
|
|
3952
|
+
offset: number;
|
|
3953
|
+
};
|
|
3954
|
+
/**
|
|
3955
|
+
* Stated so nobody has to guess: when this is true the answer is the
|
|
3956
|
+
* intersection of the id sets above, and when it is false the read stands
|
|
3957
|
+
* alone.
|
|
3958
|
+
*/
|
|
3959
|
+
intersects: boolean;
|
|
3960
|
+
}
|
|
3961
|
+
declare const DEFAULT_PAGE_SIZE = 50;
|
|
3962
|
+
declare function planQuery(query: RecordQuery): QueryPlan;
|
|
3963
|
+
/** The intersection of the id sets a plan's calls produced. Order is preserved from the first set. */
|
|
3964
|
+
declare function intersectIds(sets: Uuid[][]): Uuid[];
|
|
3965
|
+
|
|
3966
|
+
/**
|
|
3967
|
+
* 🚨 A REFUSAL IS NOT AN APP ERROR (lane RECORDS-UI-FIX, guide re-walk 2026-09-23).
|
|
3968
|
+
*
|
|
3969
|
+
* A person typing `-3` into a column that takes "at least 0" is the store WORKING: the
|
|
3970
|
+
* rule said no, the screen said so in the one notice, and the person fixed it. The default
|
|
3971
|
+
* sink printed every one of those through `console.error`, and the app's error capture
|
|
3972
|
+
* (matrx-frontend `lib/diagnostics/globalErrorCapture.ts`) counts every `console.error` —
|
|
3973
|
+
* so one refused value lit a red "2 errors" pill in the corner, telling an admin the
|
|
3974
|
+
* product had failed when a person had simply been told no.
|
|
3975
|
+
*
|
|
3976
|
+
* These are the codes a PERSON causes by what they typed or when they typed it; each one
|
|
3977
|
+
* is already drawn on the screen that asked. They are still said (`console.info`), never
|
|
3978
|
+
* silenced. Everything else — a door, the store switched off, a timeout, a class this
|
|
3979
|
+
* package did not recognise — is a failure of the system and stays `console.error`.
|
|
3980
|
+
*/
|
|
3981
|
+
declare const A_PERSONS_REFUSAL: ReadonlySet<RecordsErrorCode>;
|
|
3982
|
+
declare function isAPersonsRefusal(code: RecordsErrorCode | string): boolean;
|
|
3983
|
+
/** One organization the client could not use, with the sentence that says why. */
|
|
3984
|
+
interface OrganizationUnavailable {
|
|
3985
|
+
organization_id: Uuid;
|
|
3986
|
+
reason: string;
|
|
3987
|
+
}
|
|
3988
|
+
/** `organizationsOpen`: the organizations whose store answers, and those that do not (with why). */
|
|
3989
|
+
interface OrganizationsOpenAnswer {
|
|
3990
|
+
open: Uuid[];
|
|
3991
|
+
unavailable: OrganizationUnavailable[];
|
|
3992
|
+
}
|
|
3993
|
+
/** `metadataSearch`: every match, each carrying the organization it came from. */
|
|
3994
|
+
interface MetadataSearchAnswer {
|
|
3995
|
+
matches: Array<Record<string, unknown> & {
|
|
3996
|
+
organization_id: Uuid | null;
|
|
3997
|
+
}>;
|
|
3998
|
+
/** Organizations asked in order (the ones that answered). */
|
|
3999
|
+
organizations_covered: Uuid[];
|
|
4000
|
+
unavailable: OrganizationUnavailable[];
|
|
4001
|
+
}
|
|
4002
|
+
interface RecordsClient {
|
|
4003
|
+
/** The config this client was built with, so a screen can show who it is acting as. */
|
|
4004
|
+
readonly config: RecordsConfig;
|
|
4005
|
+
/**
|
|
4006
|
+
* THE SCOPE DOORS (`custom.context_*`): scope types are Tables kept for context, scopes Records,
|
|
4007
|
+
* context fields Fields, values cells. Built from this client's own door path. `@ai-matrx/records/scopes`.
|
|
4008
|
+
*/
|
|
4009
|
+
readonly scopes: ScopeDoors;
|
|
4010
|
+
recordWrite(args: {
|
|
4011
|
+
table_id: Uuid;
|
|
4012
|
+
data: RecordDocument;
|
|
4013
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
4014
|
+
/**
|
|
4015
|
+
* WRITE THE RECORD THIS KEY NAMES, OR UPDATE IT WHEN IT IS ALREADY THERE — one call, race-safe
|
|
4016
|
+
* (`custom.record_upsert`). `key` is the column key (or keys) that say which record this is,
|
|
4017
|
+
* and every one must carry a `unique` rule: the store refuses any other column by its name.
|
|
4018
|
+
* Two concurrent calls with the same key leave ONE record. An update goes through
|
|
4019
|
+
* `record_update` (with `expectedVersion`, its stale-write refusal); a new record through
|
|
4020
|
+
* `record_write`. Answers the record's id either way.
|
|
4021
|
+
*/
|
|
4022
|
+
recordUpsert(args: {
|
|
4023
|
+
table_id: Uuid;
|
|
4024
|
+
key: string | string[];
|
|
4025
|
+
data: RecordDocument;
|
|
4026
|
+
expectedVersion?: number;
|
|
4027
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
4028
|
+
/**
|
|
4029
|
+
* Write MANY new records of one Table in one call.
|
|
4030
|
+
*
|
|
4031
|
+
* `custom.record_write_many` asks the switch, the organization and the Table
|
|
4032
|
+
* ONCE for the whole batch and inserts the rows in one statement — which is
|
|
4033
|
+
* why a paste of 120 lines is one round trip per chunk instead of 120. It
|
|
4034
|
+
* CREATES only: there is no bulk update door, because an update carries a
|
|
4035
|
+
* per-row optimistic version and a batch would have to either drop that or
|
|
4036
|
+
* fail the whole batch for one stale row.
|
|
4037
|
+
*
|
|
4038
|
+
* It returns the new ids IN THE ORDER THE ROWS WERE HANDED IN, so a caller
|
|
4039
|
+
* can tie each id back to the line of the spreadsheet it came from. Hand in
|
|
4040
|
+
* `ids` to choose them yourself; hand in none and the door mints them.
|
|
4041
|
+
*/
|
|
4042
|
+
recordWriteMany(args: {
|
|
4043
|
+
table_id: Uuid;
|
|
4044
|
+
rows: RecordDocument[];
|
|
4045
|
+
ids?: Uuid[];
|
|
4046
|
+
}): Promise<RecordsResult<Uuid[]>>;
|
|
4047
|
+
/**
|
|
4048
|
+
* DOOR-SPEED. MANY CHANGES TO ONE TABLE IN ONE TRANSACTION, through
|
|
4049
|
+
* `custom.record_change_many`: inserts, updates (each with an optional `expected_version`)
|
|
4050
|
+
* and archives. Every update lands in ONE statement, so the store's change notice, history and
|
|
4051
|
+
* activity fire once for the batch while every row trigger still judges every row. ONE REFUSED
|
|
4052
|
+
* CHANGE REFUSES THE BATCH and nothing is saved; the store's own sentence comes back with the
|
|
4053
|
+
* change's position in the hint. The answer is one result per change, in order.
|
|
4054
|
+
*/
|
|
4055
|
+
recordChangeMany(args: {
|
|
4056
|
+
table_id: Uuid;
|
|
4057
|
+
changes: readonly RecordChange[];
|
|
4058
|
+
}): Promise<RecordsResult<RecordChangeResult[]>>;
|
|
4059
|
+
/**
|
|
4060
|
+
* A PARENT, THE EDGES IT STANDS ON AND THE ROWS THAT BELONG TO IT — ALL OR NOTHING.
|
|
4061
|
+
*
|
|
4062
|
+
* `recordWrite` and `recordWriteMany` are each ONE statement. A screen or a
|
|
4063
|
+
* server path whose unit of work is a GRAPH — an AI artifact and the lines
|
|
4064
|
+
* it produced, an order and its items, a research note and its citations —
|
|
4065
|
+
* could therefore not save it as one thing: a loop is N transactions, and a
|
|
4066
|
+
* failure on row nineteen leaves a parent standing without the lines it
|
|
4067
|
+
* promised.
|
|
4068
|
+
*
|
|
4069
|
+
* `custom.record_write_graph` is one statement, so it is one transaction. It
|
|
4070
|
+
* is NOT a second write path: it calls `custom.record_write_many` for the
|
|
4071
|
+
* rows, `public.assoc_add` for an edge that points OUT of the store (the
|
|
4072
|
+
* message a record was produced by), and `platform.relation_set` for the
|
|
4073
|
+
* parent's own declared relation to its children. Same store switch, same
|
|
4074
|
+
* editor rung on the Table, same value envelope, same undeclared-key guard,
|
|
4075
|
+
* same history rows, same realtime notice.
|
|
4076
|
+
*
|
|
4077
|
+
* ONE REFUSAL REFUSES THE WHOLE GRAPH, BY NAME — the answer says which member
|
|
4078
|
+
* failed and carries the store's own sentence about it, and nothing is
|
|
4079
|
+
* written.
|
|
4080
|
+
*
|
|
4081
|
+
* Every child MUST name a `role`: it is the key of a declared RELATION field
|
|
4082
|
+
* on the parent's Table, and an edge out of a record that names no field is
|
|
4083
|
+
* refused by the store (REL-10 / T7) because without it nothing can read the
|
|
4084
|
+
* relation's delete rule, its cardinality or its organization wall. The order
|
|
4085
|
+
* children are handed in IS the order of the relation.
|
|
4086
|
+
*/
|
|
4087
|
+
recordWriteGraph(args: {
|
|
4088
|
+
table_id: Uuid;
|
|
4089
|
+
parent: RecordDocument;
|
|
4090
|
+
/** Each child: its document, the parent FIELD it fills, and optionally its own Table. */
|
|
4091
|
+
children?: Array<{
|
|
4092
|
+
data: RecordDocument;
|
|
4093
|
+
role: string;
|
|
4094
|
+
table_id?: Uuid;
|
|
4095
|
+
position?: number;
|
|
4096
|
+
}>;
|
|
4097
|
+
/** Edges to things OUTSIDE the store. `direction` defaults to `"in"` — that thing produced this record. */
|
|
4098
|
+
edges?: Array<{
|
|
4099
|
+
entity: string;
|
|
4100
|
+
id: Uuid;
|
|
4101
|
+
direction?: "in" | "out";
|
|
4102
|
+
label?: string;
|
|
4103
|
+
role?: string;
|
|
4104
|
+
position?: number;
|
|
4105
|
+
metadata?: Record<string, unknown>;
|
|
4106
|
+
}>;
|
|
4107
|
+
}): Promise<RecordsResult<RecordGraphWritten>>;
|
|
4108
|
+
recordUpdate(args: {
|
|
4109
|
+
record_id: Uuid;
|
|
4110
|
+
patch: Record<string, unknown>;
|
|
4111
|
+
/** Leave it out and the last writer wins; supply it and a loser is TOLD. */
|
|
4112
|
+
expectedVersion?: number;
|
|
4113
|
+
}): Promise<RecordsResult<number>>;
|
|
4114
|
+
/**
|
|
4115
|
+
* A CELL THAT TAKES WORDS WHICH ARE NOT YET A CHOICE — the words become a choice of that
|
|
4116
|
+
* column everywhere and the cell takes it, in ONE transaction (lane CHOICE-COLUMN-EDIT,
|
|
4117
|
+
* `custom.record_update_adding_choices`). `add` is `{ "<column key>": ["words", ...] }`; the
|
|
4118
|
+
* cell's value in `patch` is the words, and the store turns them into the new choice's key.
|
|
4119
|
+
* Adding a choice changes the table's columns, so it needs that right; a refusal names it.
|
|
4120
|
+
* Answers the new version, like `recordUpdate`, and announces the record changed.
|
|
4121
|
+
*/
|
|
4122
|
+
recordUpdateAddingChoices(args: {
|
|
4123
|
+
record_id: Uuid;
|
|
4124
|
+
patch: Record<string, unknown>;
|
|
4125
|
+
add: Record<string, string[]>;
|
|
4126
|
+
expectedVersion?: number;
|
|
4127
|
+
}): Promise<RecordsResult<number>>;
|
|
4128
|
+
/**
|
|
4129
|
+
* The Feature Knob `custom/choice_nudge` for the signed-in person in this client's
|
|
4130
|
+
* organization: what a choice cell does with typed words that are not a choice
|
|
4131
|
+
* (`decideTypedChoice` in `choice.ts` is the one place that acts on it).
|
|
4132
|
+
*/
|
|
4133
|
+
choiceNudge(): Promise<RecordsResult<ChoiceNudge>>;
|
|
4134
|
+
/**
|
|
4135
|
+
* REC-23. Soft, and reversible within `retention`.
|
|
4136
|
+
*
|
|
4137
|
+
* 🚨 NOT FOR A TABLE. A Table is a record, so this door accepts one — and
|
|
4138
|
+
* then recurses through every record the Table contains inside a single
|
|
4139
|
+
* transaction, which is unbounded by construction and dies on `57014` at a
|
|
4140
|
+
* size the product's own import reaches in half a minute. Use
|
|
4141
|
+
* `tableArchive` below, which does the same work in resumable passes.
|
|
4142
|
+
*/
|
|
4143
|
+
recordDelete(args: {
|
|
4144
|
+
record_id: Uuid;
|
|
4145
|
+
}): Promise<RecordsResult<Timestamp>>;
|
|
4146
|
+
recordRestore(args: {
|
|
4147
|
+
record_id: Uuid;
|
|
4148
|
+
}): Promise<RecordsResult<void>>;
|
|
4149
|
+
/**
|
|
4150
|
+
* ARCHIVING A WHOLE TABLE — ONE PASS OF IT (VERIFIER-11 F3).
|
|
4151
|
+
*
|
|
4152
|
+
* One call archives at most `chunk` of the table's live records through
|
|
4153
|
+
* `custom.record_delete` (so every guard, history capture and outbox row
|
|
4154
|
+
* still happens; nothing is hard-deleted) and comes back with the numbers a
|
|
4155
|
+
* screen draws progress from. The CALLER LOOPS until `done` — that loop is
|
|
4156
|
+
* the fix, because the one thing a single statement cannot be made to do is
|
|
4157
|
+
* finish.
|
|
4158
|
+
*
|
|
4159
|
+
* `chunk: 0` changes nothing and only reports, so a screen can say "1,430
|
|
4160
|
+
* records will be archived" BEFORE a person commits to it. `includeTable:
|
|
4161
|
+
* false` empties the table and leaves it standing.
|
|
4162
|
+
*
|
|
4163
|
+
* RESUMABLE, WITHOUT A JOB ROW: what remains is read off the records
|
|
4164
|
+
* themselves every call. A pass that fails, a closed tab or a deploy mid-run
|
|
4165
|
+
* leaves a half-archived table and a next call that continues from exactly
|
|
4166
|
+
* there. A caller must therefore never report "nothing happened" after a
|
|
4167
|
+
* failed pass — `archived_total` says what really landed.
|
|
4168
|
+
*/
|
|
4169
|
+
tableArchive(args: {
|
|
4170
|
+
table_id: Uuid;
|
|
4171
|
+
/**
|
|
4172
|
+
* How many records this pass takes on. The door clamps it; it answers with what it
|
|
4173
|
+
* took. Default 50 — measured: ~35ms a record against an 8s statement timeout, so
|
|
4174
|
+
* 200 dies on `57014` and is the original defect one level up.
|
|
4175
|
+
*/
|
|
4176
|
+
chunk?: number;
|
|
4177
|
+
/** Archive the Table record itself once nothing live is left in it. Default true. */
|
|
4178
|
+
includeTable?: boolean;
|
|
4179
|
+
}): Promise<RecordsResult<TableArchiveProgress>>;
|
|
4180
|
+
/**
|
|
4181
|
+
* ONE PASS OF ARCHIVING, ON PURPOSE, A TABLE THE APP'S CODE DEPENDS ON
|
|
4182
|
+
* (`custom.table_archive_deliberately`, lane 12 P5). Such a table (`code_depends: true`) refuses
|
|
4183
|
+
* `tableArchive`, `recordDelete`, a slug / kept_for rename, `tableMove` and removal of the mark.
|
|
4184
|
+
* This door takes the table's slug TYPED by the person and a reason, refuses an agent, and then
|
|
4185
|
+
* archives through `custom.table_archive` (same progress answer; the caller loops until `done`).
|
|
4186
|
+
* Use `archiveTypedTableDeliberately` (`@ai-matrx/records/typed-table`), which loops.
|
|
4187
|
+
*/
|
|
4188
|
+
tableArchiveDeliberately(args: {
|
|
4189
|
+
table_id: Uuid;
|
|
4190
|
+
typed_slug: string;
|
|
4191
|
+
reason: string;
|
|
4192
|
+
}): Promise<RecordsResult<TableArchiveProgress>>;
|
|
4193
|
+
/**
|
|
4194
|
+
* BRINGING A WHOLE TABLE BACK — ONE PASS OF IT (`custom.table_restore`, lane TABLE-ACTIONS).
|
|
4195
|
+
*
|
|
4196
|
+
* 🚨 NOT `recordRestore` FOR A TABLE: that door brings the Table, its structure, every record
|
|
4197
|
+
* and everything built on it back in one statement and dies on `57014` (the clone's "Referral
|
|
4198
|
+
* Intake Queue 2026-Q4 (copy 7)"). This pass brings back the Table and its structure first, then
|
|
4199
|
+
* at most `chunk` records, then what was built on it — all from the one archive event — and
|
|
4200
|
+
* answers `done` when nothing the archive took is still waiting. Use {@link tableRestoreWhole}.
|
|
4201
|
+
*/
|
|
4202
|
+
tableRestore(args: {
|
|
4203
|
+
table_id: Uuid;
|
|
4204
|
+
chunk?: number;
|
|
4205
|
+
}): Promise<RecordsResult<TableRestoreProgress>>;
|
|
4206
|
+
/**
|
|
4207
|
+
* THE WHOLE RESTORE OF A TABLE — the loop every caller needs: `tableRestore` until `done`,
|
|
4208
|
+
* halving the pass on a statement timeout (a pass that timed out changed nothing). `onPass`
|
|
4209
|
+
* hears every pass's numbers. Answers the last pass, or the refusal that stopped it (what the
|
|
4210
|
+
* passes before it brought back stays back; the next call carries on from there).
|
|
4211
|
+
*/
|
|
4212
|
+
tableRestoreWhole(args: {
|
|
4213
|
+
table_id: Uuid;
|
|
4214
|
+
onPass?: (progress: TableRestoreProgress) => void;
|
|
4215
|
+
}): Promise<RecordsResult<TableRestoreProgress>>;
|
|
4216
|
+
/**
|
|
4217
|
+
* DUPLICATE A TABLE — `custom.table_duplicate` (lane TABLE-ACTIONS).
|
|
4218
|
+
*
|
|
4219
|
+
* Makes a NEW Table from one the caller may open: its settings and look, every live column (new
|
|
4220
|
+
* ids), every choice list as a new list (same words, colours, keys and order), every saved view
|
|
4221
|
+
* (filters, sorts, layouts, every id inside them pointing at the copy), and with `withRecords`
|
|
4222
|
+
* every live record (a link to another row of the same table follows to the copy's row; a link
|
|
4223
|
+
* to another table stays). `name` defaults to "<name> (copy)", "(copy 2)", …;
|
|
4224
|
+
* `organizationId` defaults to the source's organization and must be one the caller belongs to.
|
|
4225
|
+
* The source is never written. The copy is made in passes of a few seconds (any size; the
|
|
4226
|
+
* store answers "copying" until "done"), and this call loops them. Refused before anything is
|
|
4227
|
+
* made, the refusal carries the store's one sentence (not given / archived / not a member there
|
|
4228
|
+
* / a column linking across organizations).
|
|
4229
|
+
*/
|
|
4230
|
+
tableDuplicate(args: {
|
|
4231
|
+
tableId: Uuid;
|
|
4232
|
+
withRecords?: boolean;
|
|
4233
|
+
name?: string | null;
|
|
4234
|
+
organizationId?: Uuid | null;
|
|
4235
|
+
/** Called after every pass with what is copied so far (a progress bar is made of it). */
|
|
4236
|
+
onProgress?: (progress: TableDuplicateProgress) => void;
|
|
4237
|
+
}): Promise<RecordsResult<TableDuplicated>>;
|
|
4238
|
+
/**
|
|
4239
|
+
* CARRY ON A COPY — `custom.table_duplicate_continue` (lane TABLE-ACTIONS). The copy is made in
|
|
4240
|
+
* passes of a few seconds each; `tableDuplicate` loops them, and this resumes one that a closed
|
|
4241
|
+
* tab or a lost connection left unfinished (the copy is kept out of every table list until it
|
|
4242
|
+
* is done). Only the person who started it; it answers the finished copy, or refuses.
|
|
4243
|
+
*/
|
|
4244
|
+
tableDuplicateContinue(args: {
|
|
4245
|
+
copyId: Uuid;
|
|
4246
|
+
onProgress?: (progress: TableDuplicateProgress) => void;
|
|
4247
|
+
}): Promise<RecordsResult<TableDuplicated>>;
|
|
4248
|
+
/**
|
|
4249
|
+
* THE CALLER'S UNFINISHED COPIES — `custom.table_copies_in_progress` (lane TABLE-ACTIONS). Each
|
|
4250
|
+
* is still being made (carry it on with `tableDuplicateContinue`) or stopped because its source
|
|
4251
|
+
* was archived meanwhile (discard it: `tableArchive` on the copy). Nobody else can see them.
|
|
4252
|
+
*/
|
|
4253
|
+
tableCopiesInProgress(): Promise<RecordsResult<TableCopyInProgress[]>>;
|
|
4254
|
+
recordRead(args: {
|
|
4255
|
+
record_id: Uuid;
|
|
4256
|
+
withComputed?: boolean;
|
|
4257
|
+
/** Also answer `version` (read in the same round, so the read takes as long as the slower of the two). */
|
|
4258
|
+
withVersion?: boolean;
|
|
4259
|
+
organization_id?: Uuid | null;
|
|
4260
|
+
}): Promise<RecordsResult<RecordRead>>;
|
|
4261
|
+
/**
|
|
4262
|
+
* DOOR-1. A page of one Table's records THROUGH `custom.read_records`: the
|
|
4263
|
+
* store decides which rows this reader may see and which fields of them, and
|
|
4264
|
+
* a field it masked comes back present-and-null with its reason in `hidden`.
|
|
4265
|
+
* `total` is null because the door counts nothing it has not read — a count
|
|
4266
|
+
* of rows a person may not see is a leak with a number on it.
|
|
4267
|
+
*/
|
|
4268
|
+
list(args: {
|
|
4269
|
+
table_id: Uuid;
|
|
4270
|
+
/**
|
|
4271
|
+
* THE STORE'S ONE FILTER SHAPE (`RecordFilter`). Left out, this is the
|
|
4272
|
+
* whole page. Supplied, the store narrows INSIDE its own query — never the
|
|
4273
|
+
* browser, which can only ever filter the rows it was already allowed to
|
|
4274
|
+
* see and would silently drop the rest of the answer.
|
|
4275
|
+
*
|
|
4276
|
+
* It is the same object a saved view stores as `filters` and the same one
|
|
4277
|
+
* `recordAggregate` counts with, so the rows a drill-through opens are the
|
|
4278
|
+
* rows the number on the dashboard counted.
|
|
4279
|
+
*/
|
|
4280
|
+
filter?: StoreFilter;
|
|
4281
|
+
limit?: number;
|
|
4282
|
+
offset?: number;
|
|
4283
|
+
}): Promise<RecordsResult<{
|
|
4284
|
+
rows: ReadRow[];
|
|
4285
|
+
total: number | null;
|
|
4286
|
+
locked?: number;
|
|
4287
|
+
}>>;
|
|
4288
|
+
/**
|
|
4289
|
+
* DOOR-SPEED. ONE PAGE THE STORE SORTED, SEARCHED, FILTERED AND COUNTED, through
|
|
4290
|
+
* `custom.read_records_page` — the same wall, ladder, field mask and filter as `list`, with the
|
|
4291
|
+
* order (`sort`, or a hand-ordered view's positions via `view_id`), a text `search` over the
|
|
4292
|
+
* columns this reader may see (and the words of choice options), and the `total` of the
|
|
4293
|
+
* matching visible set. It is what a grid pages with: nothing reads the whole table to draw one
|
|
4294
|
+
* page. A sort on a column this reader cannot see (gone, or masked) is SKIPPED and named in
|
|
4295
|
+
* `sort_ignored` — the page still loads; one worked out on every read is refused by name.
|
|
4296
|
+
*/
|
|
4297
|
+
listPage(args: {
|
|
4298
|
+
table_id: Uuid;
|
|
4299
|
+
filter?: StoreFilter;
|
|
4300
|
+
search?: string | null;
|
|
4301
|
+
sort?: readonly RecordPageSort[];
|
|
4302
|
+
view_id?: Uuid | null;
|
|
4303
|
+
limit?: number;
|
|
4304
|
+
offset?: number;
|
|
4305
|
+
}): Promise<RecordsResult<RecordPage>>;
|
|
4306
|
+
/**
|
|
4307
|
+
* AP3-KEYSET-DOOR. THE SAME PAGE AS `listPage`, PAGED BY A CURSOR, through
|
|
4308
|
+
* `custom.read_records_keyset`: the same wall, ladder, field mask, filter, search and sort (no
|
|
4309
|
+
* hand-ordered view), the same rows in the same order — but the next page starts after the last
|
|
4310
|
+
* row's sort values and id, so a write landing mid-read never skips or repeats a row. Pass back
|
|
4311
|
+
* `cursor` as `after` (it is opaque; `null` on the last page). A cursor handed to a different
|
|
4312
|
+
* sort, filter or search is refused by name ("start from the first page"), never reinterpreted.
|
|
4313
|
+
*
|
|
4314
|
+
* Every row carries the `version` and `organization_id` it was read at, in the same statement as
|
|
4315
|
+
* its values. With `ids`, it re-reads exactly those rows among the ones the reader may see (in the
|
|
4316
|
+
* page's order; `after` ignored, `cursor` and `total` null) — get-by-id, the re-read after a write,
|
|
4317
|
+
* and the changed ids of a realtime notice.
|
|
4318
|
+
*/
|
|
4319
|
+
listKeyset(args: {
|
|
4320
|
+
table_id: Uuid;
|
|
4321
|
+
filter?: StoreFilter;
|
|
4322
|
+
search?: string | null;
|
|
4323
|
+
sort?: readonly RecordPageSort[];
|
|
4324
|
+
after?: string | null;
|
|
4325
|
+
ids?: readonly Uuid[];
|
|
4326
|
+
limit?: number;
|
|
4327
|
+
}): Promise<RecordsResult<RecordKeysetPage>>;
|
|
4328
|
+
/**
|
|
4329
|
+
* DOOR-1 FOR AN ID SET. Exactly these records of this Table, through
|
|
4330
|
+
* `custom.read_records_by_ids` — the same ladder, the same level, the same
|
|
4331
|
+
* field masking and the same page ceiling as `list`, addressed by id instead
|
|
4332
|
+
* of by page. An id the reader may not see simply does not come back, which
|
|
4333
|
+
* is the same answer `list` gives by omission.
|
|
4334
|
+
*
|
|
4335
|
+
* It exists because a realtime notice has always named the exact ids that
|
|
4336
|
+
* moved and no door could take them: three cells changing re-read a fifty-row
|
|
4337
|
+
* page in every watching browser.
|
|
4338
|
+
*/
|
|
4339
|
+
listByIds(args: {
|
|
4340
|
+
table_id: Uuid;
|
|
4341
|
+
ids: readonly Uuid[];
|
|
4342
|
+
}): Promise<RecordsResult<ReadRow[]>>;
|
|
4343
|
+
/**
|
|
4344
|
+
* DOOR-1 FOR THE ROWS THAT LEFT: a page of one Table's ARCHIVED records,
|
|
4345
|
+
* through `custom.read_records_archived` — the same ladder, the same level,
|
|
4346
|
+
* the same field masking and the same page ceiling as `list`, with the sign
|
|
4347
|
+
* of the `deleted_at` test flipped, plus who archived each one and when.
|
|
4348
|
+
*
|
|
4349
|
+
* 🚨 IT EXISTS BECAUSE ARCHIVING WAS A ONE-WAY DOOR (VERIFIER-10 F4). The
|
|
4350
|
+
* store has always had `record_restore`, and it has always done exactly the
|
|
4351
|
+
* right thing; what it did not have was any door that could LIST the records
|
|
4352
|
+
* it would act on, because every read door answers live rows only. So an
|
|
4353
|
+
* archived record was unreachable from every screen in the platform.
|
|
4354
|
+
*
|
|
4355
|
+
* `lane` is the archived-items law's two lanes — "mine" (what I archived) and
|
|
4356
|
+
* "org" (what anybody in this organization archived), which is the default.
|
|
4357
|
+
*/
|
|
4358
|
+
listArchived(args: {
|
|
4359
|
+
table_id: Uuid;
|
|
4360
|
+
lane?: ArchiveLane;
|
|
4361
|
+
limit?: number;
|
|
4362
|
+
offset?: number;
|
|
4363
|
+
}): Promise<RecordsResult<{
|
|
4364
|
+
rows: ArchivedRow[];
|
|
4365
|
+
total: number | null;
|
|
4366
|
+
}>>;
|
|
4367
|
+
query(query: RecordQuery): Promise<RecordsResult<{
|
|
4368
|
+
rows: ReadRow[];
|
|
4369
|
+
total: number | null;
|
|
4370
|
+
}>>;
|
|
4371
|
+
/**
|
|
4372
|
+
* Every Table the person can see across ALL their organizations
|
|
4373
|
+
* (`config.organizationIds`); `organization_id` is the page's optional filter
|
|
4374
|
+
* (absent = all). Each Table carries its own `organization_id`.
|
|
4375
|
+
*/
|
|
4376
|
+
tableList(args?: {
|
|
4377
|
+
organization_id?: Uuid | null;
|
|
4378
|
+
}): Promise<RecordsResult<Table[]>>;
|
|
4379
|
+
/**
|
|
4380
|
+
* ONE Table's declaration by id — `null` when this reader may not see it or it is not a Table.
|
|
4381
|
+
* The same kernel record `tableList` lists, read through `read_records_by_ids` for exactly
|
|
4382
|
+
* that id, so a screen that opens one table never lists every table to find it (a list capped
|
|
4383
|
+
* at 500 answered "no table" past the 500th).
|
|
4384
|
+
*/
|
|
4385
|
+
tableRead(args: {
|
|
4386
|
+
table_id: Uuid;
|
|
4387
|
+
organization_id?: Uuid | null;
|
|
4388
|
+
}): Promise<RecordsResult<Table | null>>;
|
|
4389
|
+
/**
|
|
4390
|
+
* ONE Table of THIS organization found by its slug — or, with no slug, by its name — in ONE
|
|
4391
|
+
* request (`custom.table_find`). `null` when there is none or this reader may not see it: the
|
|
4392
|
+
* store reads the candidates through the same read door `tableRead` uses, so a table she may
|
|
4393
|
+
* not see answers exactly like one nobody made. Where several share a slug, the oldest she may
|
|
4394
|
+
* see answers, every time (the same pick `ensureTable` makes). Never list every table to find one.
|
|
4395
|
+
*
|
|
4396
|
+
* `keptFor` (an app's table): the slug AND what the table is kept for must match — a person's own
|
|
4397
|
+
* table of the same slug is a different table and never answers. With `keptFor` and no live
|
|
4398
|
+
* match, an ARCHIVED match is answered as `{ id, organization_id, archived_at }` (no document), so
|
|
4399
|
+
* a caller says "archived — restore it", never "missing".
|
|
4400
|
+
*/
|
|
4401
|
+
tableFind(args: ({
|
|
4402
|
+
slug: string;
|
|
4403
|
+
name?: never;
|
|
4404
|
+
} | {
|
|
4405
|
+
name: string;
|
|
4406
|
+
slug?: never;
|
|
4407
|
+
}) & {
|
|
4408
|
+
keptFor?: string;
|
|
4409
|
+
}): Promise<RecordsResult<Table | null>>;
|
|
4410
|
+
/**
|
|
4411
|
+
* IS THIS TABLE IN THE ARCHIVE? (lane HUB-FIX, 2026-09-23.) The archived row for one
|
|
4412
|
+
* Table of this organization, or `null` when the archive does not hold it — which
|
|
4413
|
+
* is an ANSWER, never "it may have been deleted". A table page that cannot find a
|
|
4414
|
+
* Table asks this before saying anything: an archived Table's own address used to
|
|
4415
|
+
* read "…or it may have been deleted" when it was archived and one click from back.
|
|
4416
|
+
*/
|
|
4417
|
+
tableArchived(args: {
|
|
4418
|
+
table_id: Uuid;
|
|
4419
|
+
}): Promise<RecordsResult<ArchivedRow | null>>;
|
|
4420
|
+
/**
|
|
4421
|
+
* WHO CAN SEE EACH TABLE, AND WHETHER THE CALLER MADE IT — `custom.table_facts`
|
|
4422
|
+
* (lane HUB-FIX). `visibility` and `created_by` are record COLUMNS the Table document
|
|
4423
|
+
* never carried, so a screen that sorts Tables into lanes asks this and folds the
|
|
4424
|
+
* answer onto `tableList()`'s Tables with `withTableFacts`.
|
|
4425
|
+
*
|
|
4426
|
+
* 🚨 IT IS ITS OWN CALL, NOT PART OF `tableList()` (0.57.3). 0.57.2 folded it into
|
|
4427
|
+
* every table list, so every screen that merely LISTS tables (the field editor's
|
|
4428
|
+
* relation target, the import wizard, settings) paid a second round trip it never
|
|
4429
|
+
* used — and every test double that answers a table list had to answer it too
|
|
4430
|
+
* (records-ui 0.84.5's gate: 47 tests in 15 files red). Only the lane-sorting
|
|
4431
|
+
* screens ask.
|
|
4432
|
+
*
|
|
4433
|
+
* The door-presence pattern: when the store's catalogue does not carry the door the
|
|
4434
|
+
* answer is `null` — nothing asked, nothing invented.
|
|
4435
|
+
*/
|
|
4436
|
+
tableFacts(args?: {
|
|
4437
|
+
organization_id?: Uuid | null;
|
|
4438
|
+
}): Promise<RecordsResult<TableFact[] | null>>;
|
|
4439
|
+
/**
|
|
4440
|
+
* WHICH STORE CURRENTLY WRITES each table — `custom.where_tables_live`.
|
|
4441
|
+
*
|
|
4442
|
+
* This is a batch cutover decision, not a Table's home address: during COPY
|
|
4443
|
+
* mode an older table and its record-store copy share an id, and only this
|
|
4444
|
+
* door knows which one the organization is still using. It is intentionally
|
|
4445
|
+
* unbound from this client's organization because the door derives the answer
|
|
4446
|
+
* from each supplied table and the caller's authority.
|
|
4447
|
+
*/
|
|
4448
|
+
tablesLiveWhere(args: {
|
|
4449
|
+
table_ids: Uuid[];
|
|
4450
|
+
}): Promise<RecordsResult<TableLiveLocation[]>>;
|
|
4451
|
+
/**
|
|
4452
|
+
* WHICH ORGANIZATION A TABLE LIVES IN, BY NAME, AND WHERE IT MAY GO — `custom.table_home`
|
|
4453
|
+
* (SC-1' / SC-1-TAILS). Read FROM THE TABLE, never from the organization the client is bound
|
|
4454
|
+
* to, so it answers for a table shared from outside too. `null` = not given to this person,
|
|
4455
|
+
* or not there (the store says the same for both, on purpose). A store without the door
|
|
4456
|
+
* refuses `door_absent` — never a guessed organization.
|
|
4457
|
+
*/
|
|
4458
|
+
tableHome(args: {
|
|
4459
|
+
table_id: Uuid;
|
|
4460
|
+
}): Promise<RecordsResult<TableHome | null>>;
|
|
4461
|
+
/**
|
|
4462
|
+
* MOVE A TABLE into another organization the caller belongs to — `custom.table_move`. It
|
|
4463
|
+
* carries every Table inside it or its rows and writes the change events; refused, NOTHING
|
|
4464
|
+
* moved and the refusal carries the store's one sentence. `expected_version` is the Table's
|
|
4465
|
+
* version the caller decided on (a concurrent change refuses with "look again").
|
|
4466
|
+
*/
|
|
4467
|
+
tableMove(args: {
|
|
4468
|
+
table_id: Uuid;
|
|
4469
|
+
to_organization_id: Uuid;
|
|
4470
|
+
expected_version?: number | null;
|
|
4471
|
+
}): Promise<RecordsResult<TableMoved>>;
|
|
4472
|
+
/**
|
|
4473
|
+
* The Fields that apply. NOTION-PROPS: a two-way link's reverse Field (`isReverseField`) is left out
|
|
4474
|
+
* unless `withReverse` — every screen draws it as the table's reverse column (`reverseColumns`, with
|
|
4475
|
+
* `read_only: false`), which reads and writes its links; listed as a Field too it would draw twice.
|
|
4476
|
+
*/
|
|
4477
|
+
fields(args: {
|
|
4478
|
+
table_id: Uuid;
|
|
4479
|
+
recordType?: string;
|
|
4480
|
+
withReverse?: boolean;
|
|
4481
|
+
}): Promise<RecordsResult<Field[]>>;
|
|
4482
|
+
/**
|
|
4483
|
+
* FLD-5 / FLD-6: a list field stores the id of an option RECORD, because
|
|
4484
|
+
* every pick-list is already a Table. These are that Table's records — the
|
|
4485
|
+
* store resolves which Table from the Field's own config, so no caller has to
|
|
4486
|
+
* know it.
|
|
4487
|
+
*/
|
|
4488
|
+
fieldOptions(args: {
|
|
4489
|
+
field_id: Uuid;
|
|
4490
|
+
}): Promise<RecordsResult<StoredRecord[]>>;
|
|
4491
|
+
/**
|
|
4492
|
+
* How many records hold each choice of one choice column, keyed by the option's id
|
|
4493
|
+
* (`custom.field_choice_usage`; counts only records the caller may see). What a column editor
|
|
4494
|
+
* says before a choice that records still hold is removed: "3 records use “X-ray”."
|
|
4495
|
+
*/
|
|
4496
|
+
fieldChoiceUsage(args: {
|
|
4497
|
+
field_id: Uuid;
|
|
4498
|
+
}): Promise<RecordsResult<Record<string, ChoiceUsage>>>;
|
|
4499
|
+
/**
|
|
4500
|
+
* A column's choices saved AND the records of each removed choice moved to another choice,
|
|
4501
|
+
* kept as other values, or cleared — ONE transaction (`custom.field_update_rehoming_choices`).
|
|
4502
|
+
* `rehome` is keyed by the removed option's id. The answer carries `undo`; sending
|
|
4503
|
+
* `{ patch: { options: undo.options }, cells_back: undo.cells_back }` back through this same
|
|
4504
|
+
* call puts the list and every cell back, again in one transaction.
|
|
4505
|
+
*/
|
|
4506
|
+
fieldUpdateRehomingChoices(args: {
|
|
4507
|
+
field_id: Uuid;
|
|
4508
|
+
patch: FieldPatch;
|
|
4509
|
+
rehome?: Record<string, ChoiceRehome> | undefined;
|
|
4510
|
+
cells_back?: readonly ChoiceCellBack[] | undefined;
|
|
4511
|
+
}): Promise<RecordsResult<ChoicesRehomed>>;
|
|
4512
|
+
tableCapacity(args: {
|
|
4513
|
+
table_id: Uuid;
|
|
4514
|
+
}): Promise<RecordsResult<TableCapacity>>;
|
|
4515
|
+
/**
|
|
4516
|
+
* REC-1: a Table has to live somewhere, so a Home comes first — and a Home is
|
|
4517
|
+
* an ordinary record in the person kernel. `homeId` is therefore required and
|
|
4518
|
+
* `personKernelId()` is how a caller gets a Table to write one into.
|
|
4519
|
+
*/
|
|
4520
|
+
tableDeclare(args: {
|
|
4521
|
+
spec: Record<string, unknown>;
|
|
4522
|
+
homeId: Uuid;
|
|
4523
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
4524
|
+
/**
|
|
4525
|
+
* FIND THIS TABLE BY ITS SLUG, OR MAKE IT — ONE call, ONE transaction (`custom.table_ensure`).
|
|
4526
|
+
* The store holds a lock on (organization, slug) across the find and the make, so two tabs
|
|
4527
|
+
* saving their first record at once get the SAME table; a second call adds any column the spec
|
|
4528
|
+
* names that the table lacks and never retypes or drops one. `spec.fields` are full
|
|
4529
|
+
* `custom.field_declare` specs. Prefer `ensureTable(client, NewTableSpec)`, which builds them.
|
|
4530
|
+
*
|
|
4531
|
+
* `drift` names every column the table already has whose stored shape differs from the spec
|
|
4532
|
+
* (type, format, label, multi, required, unique) — reported, never applied. `[]` when nothing
|
|
4533
|
+
* differs; `null` only from a store too old to compare (see `FieldDrift`).
|
|
4534
|
+
*/
|
|
4535
|
+
tableEnsure(args: {
|
|
4536
|
+
spec: Record<string, unknown>;
|
|
4537
|
+
}): Promise<RecordsResult<{
|
|
4538
|
+
table_id: Uuid;
|
|
4539
|
+
home_id: Uuid | null;
|
|
4540
|
+
created: boolean;
|
|
4541
|
+
drift: FieldDrift[] | null;
|
|
4542
|
+
}>>;
|
|
4543
|
+
/**
|
|
4544
|
+
* ADD A FIELD TO A TABLE. One call, and the store does the three things no
|
|
4545
|
+
* client can do for itself: it turns a parity type into the behaviour,
|
|
4546
|
+
* modifiers, format, unit, relation target and Rules its own guards demand;
|
|
4547
|
+
* it tells the TABLE about the field (REC-1 / FLD-8 — a definition for a
|
|
4548
|
+
* field the table never declared is refused, which is the sentence every
|
|
4549
|
+
* "Add field" used to end on); and it stores the definition as a FIELD
|
|
4550
|
+
* rather than as a plain record, so the delete rules and the
|
|
4551
|
+
* formula-dependency check can see it.
|
|
4552
|
+
*
|
|
4553
|
+
* A choice list carries its `options` as words. The store keeps them the only
|
|
4554
|
+
* way FLD-5 / FLD-6 allows — as the records of a Table it declares for them —
|
|
4555
|
+
* so nobody is made to build a table before they can have a dropdown.
|
|
4556
|
+
*/
|
|
4557
|
+
fieldDeclare(args: {
|
|
4558
|
+
table_id: Uuid;
|
|
4559
|
+
spec: NewFieldDeclaration;
|
|
4560
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
4561
|
+
/** One field's own settings. What it HOLDS is a conversion and is refused here by name. */
|
|
4562
|
+
fieldUpdate(args: {
|
|
4563
|
+
field_id: Uuid;
|
|
4564
|
+
patch: FieldPatch;
|
|
4565
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
4566
|
+
/**
|
|
4567
|
+
* CHANGE WHAT A COLUMN HOLDS, through `custom.migrate_retype` (FLD-4 / T12). `to` is the store's
|
|
4568
|
+
* behaviour word — `text`, `range` (numbers and dates), `boolean`, `list`, `relation`. Every value
|
|
4569
|
+
* that converts is converted; every value that does not is kept in that record's `_retired`
|
|
4570
|
+
* with the reason, never coerced and never deleted. The answer counts both.
|
|
4571
|
+
*/
|
|
4572
|
+
migrateRetype(args: {
|
|
4573
|
+
field_id: Uuid;
|
|
4574
|
+
to: string;
|
|
4575
|
+
note?: string;
|
|
4576
|
+
}): Promise<RecordsResult<FieldRetyped>>;
|
|
4577
|
+
/**
|
|
4578
|
+
* MERGE ONE RECORD INTO ANOTHER, through `custom.migrate_merge` (T5 / REC-21). The loser's values
|
|
4579
|
+
* the winner did not hold move across, the ones that differ are kept as ranked alternates, every
|
|
4580
|
+
* link to the loser now points at the winner, and the loser is archived with its id resolving to
|
|
4581
|
+
* the winner. Editor on BOTH records is decided first. The answer's `migration_id` is what
|
|
4582
|
+
* `migrateUndo` takes.
|
|
4583
|
+
*/
|
|
4584
|
+
migrateMerge(args: {
|
|
4585
|
+
winner_id: Uuid;
|
|
4586
|
+
loser_id: Uuid;
|
|
4587
|
+
note?: string | null;
|
|
4588
|
+
}): Promise<RecordsResult<RecordsMerged>>;
|
|
4589
|
+
/** Put a recorded Migration back (`custom.migrate_undo`): a retype or a merge, by its id. */
|
|
4590
|
+
migrateUndo(args: {
|
|
4591
|
+
migration_id: Uuid;
|
|
4592
|
+
}): Promise<RecordsResult<MigrationUndone>>;
|
|
4593
|
+
/**
|
|
4594
|
+
* SPLIT ONE RECORD IN TWO, through `custom.migrate_split` (Rule 11 / REC-22). The named values
|
|
4595
|
+
* MOVE to a new record of the same Table; the original keeps its id, so every link to it still
|
|
4596
|
+
* resolves. Editor on the record is decided first. `migrateUndo(migration_id)` puts it back.
|
|
4597
|
+
*/
|
|
4598
|
+
migrateSplit(args: {
|
|
4599
|
+
record_id: Uuid;
|
|
4600
|
+
moved_keys: string[];
|
|
4601
|
+
note?: string | null;
|
|
4602
|
+
}): Promise<RecordsResult<RecordSplit>>;
|
|
4603
|
+
/**
|
|
4604
|
+
* EXTRACT A PARENT, through `custom.migrate_extract_parent` (Rule 11 / test 5). The named values
|
|
4605
|
+
* are COPIED up into a new record of `parent_table_id`, and this record is put under it. Its old
|
|
4606
|
+
* parent, if any, becomes the new parent's parent. `migrateUndo(migration_id)` puts it back.
|
|
4607
|
+
*/
|
|
4608
|
+
migrateExtractParent(args: {
|
|
4609
|
+
record_id: Uuid;
|
|
4610
|
+
parent_table_id: Uuid;
|
|
4611
|
+
moved_keys: string[];
|
|
4612
|
+
note?: string | null;
|
|
4613
|
+
}): Promise<RecordsResult<ParentExtracted>>;
|
|
4614
|
+
/** The Migration log for one record or Table (`custom.migrations`), newest first. */
|
|
4615
|
+
migrations(args: {
|
|
4616
|
+
target_id?: Uuid | null;
|
|
4617
|
+
limit?: number;
|
|
4618
|
+
}): Promise<RecordsResult<MigrationEntry[]>>;
|
|
4619
|
+
/**
|
|
4620
|
+
* ONE RECORD ON EITHER CLOCK, through `custom.query_record_as_of` (Rule 10 / test 6).
|
|
4621
|
+
* `recorded_at` answers what the store SAID at that moment; `world_on` answers what was TRUE of
|
|
4622
|
+
* the world on that date, read from `dated` values. Both may be given. `null` data means the
|
|
4623
|
+
* record is not visible to this person (or did not exist then) — an absence, not an empty record.
|
|
4624
|
+
*/
|
|
4625
|
+
recordAsOf(args: {
|
|
4626
|
+
record_id: Uuid;
|
|
4627
|
+
recorded_at?: string | null;
|
|
4628
|
+
world_on?: string | null;
|
|
4629
|
+
}): Promise<RecordsResult<Record<string, unknown> | null>>;
|
|
4630
|
+
/**
|
|
4631
|
+
* REL-DISP. THE WORDS ONE RELATION CELL SHOWS, resolved by the store through
|
|
4632
|
+
* that column's own display spec — one column or several, joined by its
|
|
4633
|
+
* separator. Never resolve a relation label any other way: the store's
|
|
4634
|
+
* `custom._words_for` is the one body that decides what a record is called, it
|
|
4635
|
+
* asks the read-access ladder BEFORE it reads the name, and a record this reader
|
|
4636
|
+
* may not open comes back as the withheld sentence rather than its name or id.
|
|
4637
|
+
* A value that is not an id is handed straight back — it is already words.
|
|
4638
|
+
*/
|
|
4639
|
+
relationWords(args: {
|
|
4640
|
+
field_id: Uuid;
|
|
4641
|
+
value: string;
|
|
4642
|
+
}): Promise<RecordsResult<string | null>>;
|
|
4643
|
+
/**
|
|
4644
|
+
* The same answer for a WHOLE PAGE of cells in one round trip. Prefer this
|
|
4645
|
+
* wherever a grid, board, list or picker resolves more than one chip: the
|
|
4646
|
+
* per-id lane is what made a page of relation cells a page of requests.
|
|
4647
|
+
*/
|
|
4648
|
+
relationWordsMany(args: RelationWordsManyArgs): Promise<RecordsResult<Record<string, string>> & {
|
|
4649
|
+
archived?: readonly string[];
|
|
4650
|
+
icons?: Record<string, RelationIcons>;
|
|
4651
|
+
}>;
|
|
4652
|
+
/**
|
|
4653
|
+
* VISION-REACH G1. Which records of `table_id` each name names — its name column, case and
|
|
4654
|
+
* spacing ignored, only records this reader may see. Hand the answer to `relationNameIndexOf`
|
|
4655
|
+
* and pass that to the coercion as `relationNames`. Up to 5,000 names a call; more are sent in
|
|
4656
|
+
* groups by this method.
|
|
4657
|
+
*/
|
|
4658
|
+
relationNamesMatch(args: {
|
|
4659
|
+
table_id: Uuid;
|
|
4660
|
+
names: string[];
|
|
4661
|
+
}): Promise<RecordsResult<RelationNamesAnswer>>;
|
|
4662
|
+
/**
|
|
4663
|
+
* VIEWS-AND-FIELDS BL (REL-9). The REVERSE COLUMNS of a Table: one per relation column of another
|
|
4664
|
+
* table (or this one) that links here, read-only, virtual — never a Field of this Table, so
|
|
4665
|
+
* `applicableFields` does not list them. A linking table this reader may not know is left out.
|
|
4666
|
+
*/
|
|
4667
|
+
reverseColumns(args: {
|
|
4668
|
+
table_id: Uuid;
|
|
4669
|
+
}): Promise<RecordsResult<ReverseColumn[]>>;
|
|
4670
|
+
/**
|
|
4671
|
+
* A page of records' links through ONE reverse column, in one round trip per 200 records:
|
|
4672
|
+
* `{ [record id]: { total, links: [{ id, words }] } }`, only linking records this reader may see.
|
|
4673
|
+
* `limit` (1–50) and `offset` page one record's links — a record with thousands of links costs
|
|
4674
|
+
* one count and one page. A record with no links answers `{ total: 0, links: [] }`.
|
|
4675
|
+
*/
|
|
4676
|
+
reverseLinksMany(args: ReverseLinksManyArgs): Promise<RecordsResult<Record<string, ReverseLinks>>>;
|
|
4677
|
+
/**
|
|
4678
|
+
* The same, through SEVERAL reverse columns in ONE call (`custom.reverse_links_many_fields`):
|
|
4679
|
+
* `{ [source field id]: { [record id]: { total, links } } }`. A store without the door answers
|
|
4680
|
+
* `door_absent` — ask `reverseLinksMany` per column then.
|
|
4681
|
+
*/
|
|
4682
|
+
reverseLinksFields(args: ReverseLinksFieldsArgs): Promise<RecordsResult<Record<string, Record<string, ReverseLinks>>>>;
|
|
4683
|
+
/**
|
|
4684
|
+
* NOTION-PROPS. A TWO-WAY LINK: makes (or returns) the reverse Field of relation `field_id` on its
|
|
4685
|
+
* target table (`custom.relation_reverse_field`), so the link is a column there that edits the same
|
|
4686
|
+
* links. Its key is the reverse column's key; `label` defaults to the linking table's name.
|
|
4687
|
+
*/
|
|
4688
|
+
relationReverseField(args: {
|
|
4689
|
+
field_id: Uuid;
|
|
4690
|
+
label?: string;
|
|
4691
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
4692
|
+
/**
|
|
4693
|
+
* NOTION-PROPS. Adds and removes links from the reverse side of a two-way link
|
|
4694
|
+
* (`custom.relation_reverse_set`): each id becomes a write of THAT record's forward Field.
|
|
4695
|
+
* Answers how many records changed.
|
|
4696
|
+
*/
|
|
4697
|
+
relationReverseSet(args: {
|
|
4698
|
+
record_id: Uuid;
|
|
4699
|
+
field_id: Uuid;
|
|
4700
|
+
add?: readonly Uuid[];
|
|
4701
|
+
remove?: readonly Uuid[];
|
|
4702
|
+
}): Promise<RecordsResult<number>>;
|
|
4703
|
+
/** Take a field off a table. Refuses the title field, the last field, and one another field reads through. */
|
|
4704
|
+
fieldRetire(args: {
|
|
4705
|
+
field_id: Uuid;
|
|
4706
|
+
}): Promise<RecordsResult<boolean>>;
|
|
4707
|
+
/**
|
|
4708
|
+
* Bring a removed column back (`custom.field_restore`): the set that was retired with it, the
|
|
4709
|
+
* Table's declaration of those columns, and the links they made. The values never left.
|
|
4710
|
+
*/
|
|
4711
|
+
fieldRestore(args: {
|
|
4712
|
+
field_id: Uuid;
|
|
4713
|
+
}): Promise<RecordsResult<boolean>>;
|
|
4714
|
+
/**
|
|
4715
|
+
* DUPLICATE PROPERTY (Notion N5) — `custom.field_duplicate`: a new column right after this one, named
|
|
4716
|
+
* "<name> (1)", the same kind (choices with their colours, unit, link, formula, rules, sensitivity), and
|
|
4717
|
+
* every record's value copied into it in one statement. A link column copies its definition only (its
|
|
4718
|
+
* values are links); a formula, lookup or roll-up works its answer out itself. Needs the table's
|
|
4719
|
+
* add-a-column rung, the same as `fieldDeclare`.
|
|
4720
|
+
*/
|
|
4721
|
+
fieldDuplicate(args: {
|
|
4722
|
+
field_id: Uuid;
|
|
4723
|
+
}): Promise<RecordsResult<FieldDuplicated>>;
|
|
4724
|
+
/**
|
|
4725
|
+
* CHAIR-ROLLUP-HONEST. Is a column this lookup or roll-up reads archived — the link it reads
|
|
4726
|
+
* through, a back-link's linking column, or the far column it totals (`custom.field_source_archived`)?
|
|
4727
|
+
* `null` while every source is live. Bring it back with `fieldRestore({ field_id })`.
|
|
4728
|
+
*/
|
|
4729
|
+
fieldSourceArchived(args: {
|
|
4730
|
+
field_id: Uuid;
|
|
4731
|
+
}): Promise<RecordsResult<SourceArchived | null>>;
|
|
4732
|
+
/**
|
|
4733
|
+
* A TABLE AS A KIND (KINDS-GLUE wave 3, N1): `custom.table_kind_facts` verbatim — the Table's
|
|
4734
|
+
* live Fields, choices and stamp, as the asking person. The door finds the Table's organization
|
|
4735
|
+
* itself, so this works for a Table in any organization the person may open; anything else is
|
|
4736
|
+
* refused (`42501`, the store's sentence).
|
|
4737
|
+
*/
|
|
4738
|
+
tableKindFacts(args: {
|
|
4739
|
+
table_id: Uuid;
|
|
4740
|
+
}): Promise<RecordsResult<TableKindFacts>>;
|
|
4741
|
+
/**
|
|
4742
|
+
* A TABLE'S ACCESS LEVEL (CONFIDENTIAL-BY-ORG-ADMIN): `custom.table_level_facts` verbatim - its level,
|
|
4743
|
+
* readers, who approves a change (`set_by`) and whether THIS person may (`can_set`). Draw the control only
|
|
4744
|
+
* when `can_set` is true; anyone who may know the table may ask.
|
|
4745
|
+
*/
|
|
4746
|
+
tableLevelFacts(args: {
|
|
4747
|
+
table_id: Uuid;
|
|
4748
|
+
}): Promise<RecordsResult<TableLevelFacts>>;
|
|
4749
|
+
/**
|
|
4750
|
+
* MAKE A CUSTOM TABLE CONFIDENTIAL, or change whom it names (`custom.set_table_confidential`). Succeeds
|
|
4751
|
+
* only for an owner/admin of the table's own organization on an ordinary custom table; the approver, seat,
|
|
4752
|
+
* reason and date are recorded. `readers` is the list of `{field, level}` rules (a person field of the
|
|
4753
|
+
* table); `reason` is required.
|
|
4754
|
+
*/
|
|
4755
|
+
setTableConfidential(args: {
|
|
4756
|
+
table_id: Uuid;
|
|
4757
|
+
readers: TableReaderRule[];
|
|
4758
|
+
reason: string;
|
|
4759
|
+
}): Promise<RecordsResult<TableLevelSet>>;
|
|
4760
|
+
/** THE WAY BACK: the same caller rule, the table is Organization again (`custom.set_table_organization`). */
|
|
4761
|
+
setTableOrganization(args: {
|
|
4762
|
+
table_id: Uuid;
|
|
4763
|
+
reason: string;
|
|
4764
|
+
}): Promise<RecordsResult<TableLevelSet>>;
|
|
4765
|
+
/**
|
|
4766
|
+
* THE COLUMNS THIS TABLE HAD AND NO LONGER HAS (grids review 3): its retired Field records,
|
|
4767
|
+
* newest first, through the same archived door the Table archive uses — addressed at the Field
|
|
4768
|
+
* kernel (every Field is a record in it) and paged until the door answers short.
|
|
4769
|
+
*/
|
|
4770
|
+
fieldsRetired(args: {
|
|
4771
|
+
table_id: Uuid;
|
|
4772
|
+
}): Promise<RecordsResult<ArchivedRow[]>>;
|
|
4773
|
+
/** What the registry says about a token, and whether it can hold a value at all. */
|
|
4774
|
+
entityTable(args: {
|
|
4775
|
+
token: string;
|
|
4776
|
+
}): Promise<RecordsResult<EntityTableFacts>>;
|
|
4777
|
+
/** The fields THIS organization added to that standard table. */
|
|
4778
|
+
entityFields(args: {
|
|
4779
|
+
token: string;
|
|
4780
|
+
}): Promise<RecordsResult<Field[]>>;
|
|
4781
|
+
/** The fields EVERY named organization added to that standard table, with their choices, in one read. */
|
|
4782
|
+
entityFieldsAcross(args: {
|
|
4783
|
+
token: string;
|
|
4784
|
+
organization_ids: Uuid[];
|
|
4785
|
+
}): Promise<RecordsResult<EntityFieldsAcross>>;
|
|
4786
|
+
/** Add a column to a standard table. An organization admin's right - it changes the table for everybody. */
|
|
4787
|
+
entityFieldDeclare(args: {
|
|
4788
|
+
token: string;
|
|
4789
|
+
spec: NewEntityFieldDeclaration;
|
|
4790
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
4791
|
+
/** One field's own settings. A TYPE change is refused here by name, as it is on a custom table. */
|
|
4792
|
+
entityFieldUpdate(args: {
|
|
4793
|
+
field_id: Uuid;
|
|
4794
|
+
patch: Record<string, unknown>;
|
|
4795
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
4796
|
+
/** Take a custom field off a standard table. The values already written stay in each row. */
|
|
4797
|
+
entityFieldRetire(args: {
|
|
4798
|
+
field_id: Uuid;
|
|
4799
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
4800
|
+
/** May this person add a column here - and if not, the store's own sentence saying why. */
|
|
4801
|
+
entityFieldRights(args: {
|
|
4802
|
+
token: string;
|
|
4803
|
+
}): Promise<RecordsResult<EntityFieldRights>>;
|
|
4804
|
+
/** REC-53 in one answer: the row's real columns AND its custom values AND the definitions. */
|
|
4805
|
+
entityRecordRead(args: {
|
|
4806
|
+
token: string;
|
|
4807
|
+
record_id: Uuid;
|
|
4808
|
+
}): Promise<RecordsResult<EntityRecordRead>>;
|
|
4809
|
+
/**
|
|
4810
|
+
* AP-4: the custom rows that link to one platform record, by which field and in which table.
|
|
4811
|
+
* Keyed by the ROW's organization (`organization_id`), never the client's active one. Paged:
|
|
4812
|
+
* pass the previous answer's `next_cursor` as `cursor`.
|
|
4813
|
+
*/
|
|
4814
|
+
entityBackLinks(args: {
|
|
4815
|
+
token: string;
|
|
4816
|
+
record_id: Uuid;
|
|
4817
|
+
organization_id: Uuid;
|
|
4818
|
+
limit?: number;
|
|
4819
|
+
cursor?: string | null;
|
|
4820
|
+
}): Promise<RecordsResult<EntityBackLinks>>;
|
|
4821
|
+
/**
|
|
4822
|
+
* THE one write door for a standard row (`custom.entity_row_write`, as the person): custom values
|
|
4823
|
+
* as a patch (a key left out is left alone, a key set to null is cleared with its envelope),
|
|
4824
|
+
* archive / restore, and real columns only where the store lists them. The row's own organization
|
|
4825
|
+
* governs; `expected_version` refuses a stale write; a change that changes nothing writes nothing.
|
|
4826
|
+
*/
|
|
4827
|
+
entityRowWrite(args: {
|
|
4828
|
+
token: string;
|
|
4829
|
+
/**
|
|
4830
|
+
* null ADDS a row (chairblk3_a): only for a token whose API facts say `create_via: "insert"`
|
|
4831
|
+
* (`drill_describe(...).api.create_via` — task and project), as one insert AS THE PERSON in
|
|
4832
|
+
* `organization_id` (default: this client's organization); the answer carries `created: true`
|
|
4833
|
+
* and the new `id`. Every other token refuses in its own words.
|
|
4834
|
+
*/
|
|
4835
|
+
record_id: Uuid | null;
|
|
4836
|
+
/** A change by id: only to say which organization the row must belong to. A new row: where it goes. */
|
|
4837
|
+
organization_id?: Uuid | null;
|
|
4838
|
+
custom?: Record<string, unknown>;
|
|
4839
|
+
columns?: Record<string, unknown>;
|
|
4840
|
+
expected_version?: number | null;
|
|
4841
|
+
archive?: boolean | null;
|
|
4842
|
+
}): Promise<RecordsResult<EntityRowWritten>>;
|
|
4843
|
+
/** Rows of that standard table with this custom value. Refuses a field nobody declared. */
|
|
4844
|
+
entityRecordsFind(args: {
|
|
4845
|
+
token: string;
|
|
4846
|
+
key: string;
|
|
4847
|
+
value?: unknown;
|
|
4848
|
+
limit?: number;
|
|
4849
|
+
offset?: number;
|
|
4850
|
+
}): Promise<RecordsResult<EntityRecordsFound>>;
|
|
4851
|
+
/** The kernel Tables a caller writes a Home, a Field or a Rule into. */
|
|
4852
|
+
personKernelId(): Promise<RecordsResult<Uuid>>;
|
|
4853
|
+
fieldKernelId(): Promise<RecordsResult<Uuid>>;
|
|
4854
|
+
ruleKernelId(): Promise<RecordsResult<Uuid>>;
|
|
4855
|
+
/** Every record the Rule says is a member. A saved view's list is this, not a filter a screen ran. */
|
|
4856
|
+
/** PRODUCTS row 7 — the whole board: its stage column, its stages in the declared
|
|
4857
|
+
* order, and every Rule WITH the sentence it says when it refuses. */
|
|
4858
|
+
pipelineRead(args: {
|
|
4859
|
+
table_id: Uuid;
|
|
4860
|
+
}): Promise<RecordsResult<Pipeline>>;
|
|
4861
|
+
/** The store's own count and total per column, over what this person may see. */
|
|
4862
|
+
pipelineBoard(args: {
|
|
4863
|
+
table_id: Uuid;
|
|
4864
|
+
measure?: string | null;
|
|
4865
|
+
/**
|
|
4866
|
+
* S2-PRIME — the view's question, either shape (`StoreFilter`). Given, the headings count and
|
|
4867
|
+
* total exactly the cards the same filter puts on the board (`custom.pipeline_board`'s
|
|
4868
|
+
* four-argument door); left out, the whole table this person may see, as before.
|
|
4869
|
+
*/
|
|
4870
|
+
filter?: StoreFilter | null;
|
|
4871
|
+
}): Promise<RecordsResult<PipelineColumn[]>>;
|
|
4872
|
+
/** Whether this card may go to that column — asked BEFORE the finger lets go. */
|
|
4873
|
+
pipelineTransitionRefusal(args: {
|
|
4874
|
+
record_id: Uuid;
|
|
4875
|
+
to: string;
|
|
4876
|
+
}): Promise<RecordsResult<PipelineVerdict>>;
|
|
4877
|
+
/**
|
|
4878
|
+
* Move a record to a stage. An ORDINARY record write, judged by the same Rules.
|
|
4879
|
+
*
|
|
4880
|
+
* It answers an OBJECT on every path. A gate whose `on_fail` is `require_approval`
|
|
4881
|
+
* comes back `applied: false` with the wait it filed — the record has NOT moved, and a
|
|
4882
|
+
* screen that treated the call's success as the move's success would show the card in
|
|
4883
|
+
* the wrong column while somebody is still deciding.
|
|
4884
|
+
*/
|
|
4885
|
+
pipelineMove(args: {
|
|
4886
|
+
record_id: Uuid;
|
|
4887
|
+
to: string;
|
|
4888
|
+
also?: Record<string, unknown>;
|
|
4889
|
+
expected_version?: number | null;
|
|
4890
|
+
}): Promise<RecordsResult<PipelineMoveResult>>;
|
|
4891
|
+
/**
|
|
4892
|
+
* MOVE MANY CARDS IN ONE CALL (lane S4, `custom.pipeline_move_many`). Each card is judged by
|
|
4893
|
+
* `pipeline_move` exactly as one is, in its own savepoint: a refused card writes nothing and the
|
|
4894
|
+
* others still land. `expected_version` is required per card — a card that changed since the
|
|
4895
|
+
* board loaded answers `changed_since_loaded` and is never overwritten. A refusal of the WHOLE
|
|
4896
|
+
* call (a stranger, an empty batch, more than the `custom/batch_items_max` knob) is the error.
|
|
4897
|
+
*/
|
|
4898
|
+
pipelineMoveMany(args: {
|
|
4899
|
+
moves: PipelineMoveManyItem[];
|
|
4900
|
+
}): Promise<RecordsResult<PipelineMoveMany>>;
|
|
4901
|
+
/** Declare (or re-state) a pipeline: the stage column and its transition Rules. */
|
|
4902
|
+
pipelineDeclare(args: {
|
|
4903
|
+
table_id: Uuid;
|
|
4904
|
+
spec: PipelineSpec;
|
|
4905
|
+
}): Promise<RecordsResult<PipelineDeclared>>;
|
|
4906
|
+
/** Which column of this table holds its stage, or null when it is not a board. */
|
|
4907
|
+
tableStageField(args: {
|
|
4908
|
+
table_id: Uuid;
|
|
4909
|
+
}): Promise<RecordsResult<string | null>>;
|
|
4910
|
+
/** The closed list of what a gate does when it says no — the store is the authority. */
|
|
4911
|
+
stageRuleOnFailKinds(): Promise<RecordsResult<{
|
|
4912
|
+
behaviour: StageRuleOnFail;
|
|
4913
|
+
note: string;
|
|
4914
|
+
}[]>>;
|
|
4915
|
+
/** Whether this organization's gates refuse or warn. One opinion, asked once. */
|
|
4916
|
+
stageRuleEnforcement(): Promise<RecordsResult<StageRuleEnforcement>>;
|
|
4917
|
+
/** What is waiting on this card: approvals filed against its own stage column. */
|
|
4918
|
+
recordStagePending(args: {
|
|
4919
|
+
record_id: Uuid;
|
|
4920
|
+
}): Promise<RecordsResult<StagePending[]>>;
|
|
4921
|
+
/** The same question for a whole board, in ONE call — what a Kanban badges cards from. */
|
|
4922
|
+
pipelinePending(args: {
|
|
4923
|
+
table_id: Uuid;
|
|
4924
|
+
}): Promise<RecordsResult<StagePendingOnBoard[]>>;
|
|
4925
|
+
/**
|
|
4926
|
+
* WHAT THIS GATE WOULD DO TO THIS BOARD TODAY — for a gate that has not been saved.
|
|
4927
|
+
*
|
|
4928
|
+
* The settings screen calls it on every edit of the condition, which is why it takes
|
|
4929
|
+
* the gate rather than a rule id: no saved-rule door can answer about a rule that does
|
|
4930
|
+
* not exist yet. The store compiles it with the same compiler `pipelineDeclare` uses,
|
|
4931
|
+
* so the number here and the refusal at the door are the same rule — a preview with its
|
|
4932
|
+
* own compiler would be wrong exactly at the edge of the condition, which is the only
|
|
4933
|
+
* place anybody looks.
|
|
4934
|
+
*
|
|
4935
|
+
* A gate that does not say what it demands is REFUSED, not answered zero: "no cards
|
|
4936
|
+
* would be stopped" beside a half-written rule is the sentence that gets it saved.
|
|
4937
|
+
*/
|
|
4938
|
+
pipelineGatePreview(args: {
|
|
4939
|
+
table_id: Uuid;
|
|
4940
|
+
stage: string;
|
|
4941
|
+
gate: PipelineGate | Record<string, unknown>;
|
|
4942
|
+
}): Promise<RecordsResult<PipelineGatePreview>>;
|
|
4943
|
+
/**
|
|
4944
|
+
* SERVER LANE ONLY. `custom.rule_members` walks the whole scope table through the evaluator and
|
|
4945
|
+
* returns STORED rows — no read-access ladder, no masking — so no browser role holds EXECUTE on it
|
|
4946
|
+
* and it answers 42501 from a signed-in seat. A screen reads a Rule's members through
|
|
4947
|
+
* `ruleMembersVisible`.
|
|
4948
|
+
*/
|
|
4949
|
+
ruleMembers(args: {
|
|
4950
|
+
rule_id: Uuid;
|
|
4951
|
+
}): Promise<RecordsResult<StoredRecord[]>>;
|
|
4952
|
+
/**
|
|
4953
|
+
* S2-PRIME — THE MEMBERS OF A MEMBERSHIP RULE THIS PERSON MAY SEE, a page at a time
|
|
4954
|
+
* (`custom.rule_members_visible`): the list door asked the Rule's own test, so the rows are the
|
|
4955
|
+
* read door's — the same ladder, masked documents, the same page ceiling.
|
|
4956
|
+
*/
|
|
4957
|
+
ruleMembersVisible(args: {
|
|
4958
|
+
rule_id: Uuid;
|
|
4959
|
+
limit?: number;
|
|
4960
|
+
offset?: number;
|
|
4961
|
+
}): Promise<RecordsResult<ReadRow[]>>;
|
|
4962
|
+
/** Is this one record a member, and WHY — the store's own answer. */
|
|
4963
|
+
ruleMembership(args: {
|
|
4964
|
+
rule_id: Uuid;
|
|
4965
|
+
record_id: Uuid;
|
|
4966
|
+
}): Promise<RecordsResult<unknown>>;
|
|
4967
|
+
/** Run a stored Rule against a document. */
|
|
4968
|
+
ruleRun(args: {
|
|
4969
|
+
rule_id: Uuid;
|
|
4970
|
+
values: Record<string, unknown>;
|
|
4971
|
+
context?: Record<string, unknown>;
|
|
4972
|
+
}): Promise<RecordsResult<unknown>>;
|
|
4973
|
+
/** Evaluate a Rule expression that has not been stored — the conditional logic a form runner asks about. */
|
|
4974
|
+
ruleEval(args: {
|
|
4975
|
+
expr: unknown;
|
|
4976
|
+
values: Record<string, unknown>;
|
|
4977
|
+
context?: Record<string, unknown>;
|
|
4978
|
+
}): Promise<RecordsResult<unknown>>;
|
|
4979
|
+
/**
|
|
4980
|
+
* Write ONE Rule as a real Rule. `recordWrite` into the Rule kernel makes a
|
|
4981
|
+
* valid Rule document that carries `data_class = 'record'`, and every reader
|
|
4982
|
+
* that looks for a Rule looks for the class — `custom.agg_subscriptions`
|
|
4983
|
+
* selects `where data_class = 'rule'` — so a subscription written that way
|
|
4984
|
+
* fires at nobody. This is the door that closes it.
|
|
4985
|
+
*/
|
|
4986
|
+
/** This organization's forms, with how many answers arrived and how many are in the table. */
|
|
4987
|
+
forms(args?: {
|
|
4988
|
+
table_id?: Uuid | null;
|
|
4989
|
+
}): Promise<RecordsResult<FormSummary[]>>;
|
|
4990
|
+
/**
|
|
4991
|
+
* THIS ORGANIZATION'S BOOKING PAGES (PRODUCTS row 14), with the numbers that make
|
|
4992
|
+
* the list worth opening: how many are booked, cancelled, still ahead, and how many
|
|
4993
|
+
* slots somebody is holding right now. A booking page is an `anon_form`, so it is
|
|
4994
|
+
* opened and closed with `anonPublish` exactly as a form is.
|
|
4995
|
+
*/
|
|
4996
|
+
bookings(args?: {
|
|
4997
|
+
table_id?: Uuid | null;
|
|
4998
|
+
}): Promise<RecordsResult<BookingSummary[]>>;
|
|
4999
|
+
/**
|
|
5000
|
+
* CREATE OR RE-STATE ONE BOOKING PAGE over one Table. `admin` on the Table,
|
|
5001
|
+
* because a booking page decides what a stranger may write into it and which
|
|
5002
|
+
* hours of the organization's week are on offer.
|
|
5003
|
+
*
|
|
5004
|
+
* `slot`, `status` and `booked_with` are the store's to fill in: a question
|
|
5005
|
+
* naming any of the three is refused BY NAME, so a page cannot be built that
|
|
5006
|
+
* lets a visitor choose their own status. It does NOT publish — `anonPublish`
|
|
5007
|
+
* is the one act that opens a public surface, for a booking page exactly as
|
|
5008
|
+
* for a form.
|
|
5009
|
+
*
|
|
5010
|
+
* Until 2026-09-21 this door had no client method, so the ONLY way to a
|
|
5011
|
+
* booking page was to ask an agent for one. The agent path is the faster one,
|
|
5012
|
+
* never the only one.
|
|
5013
|
+
*/
|
|
5014
|
+
bookingDeclare(args: {
|
|
5015
|
+
table_id: Uuid;
|
|
5016
|
+
title: string;
|
|
5017
|
+
questions: unknown[];
|
|
5018
|
+
availability?: Partial<BookingAvailability> | null;
|
|
5019
|
+
presentation?: Record<string, unknown> | null;
|
|
5020
|
+
submission_cap?: number | null;
|
|
5021
|
+
quarantine_rule_id?: Uuid | null;
|
|
5022
|
+
notify_rule_id?: Uuid | null;
|
|
5023
|
+
form_id?: Uuid | null;
|
|
5024
|
+
slug?: string | null;
|
|
5025
|
+
home_id?: Uuid | null;
|
|
5026
|
+
}): Promise<RecordsResult<BookingDeclared>>;
|
|
5027
|
+
/** Create or re-state one form. A question naming no Field of that Table is refused BY NAME. */
|
|
5028
|
+
formDeclare(args: {
|
|
5029
|
+
table_id: Uuid;
|
|
5030
|
+
title: string;
|
|
5031
|
+
questions: unknown[];
|
|
5032
|
+
presentation?: Record<string, unknown> | null;
|
|
5033
|
+
submission_cap?: number | null;
|
|
5034
|
+
quarantine_rule_id?: Uuid | null;
|
|
5035
|
+
notify_rule_id?: Uuid | null;
|
|
5036
|
+
form_id?: Uuid | null;
|
|
5037
|
+
slug?: string | null;
|
|
5038
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5039
|
+
/**
|
|
5040
|
+
* WHICH OF A FORM'S QUESTIONS ARE ASKED, given the answers so far — for the OWNER's preview of
|
|
5041
|
+
* a draft (`custom.form_preview_asks`). One row per question in order; `asked` is false only
|
|
5042
|
+
* when the store's own Rule said so. Undecided and unworkable conditions are asked, the second
|
|
5043
|
+
* with the store's sentence in `said`.
|
|
5044
|
+
*/
|
|
5045
|
+
formPreviewAsks(args: {
|
|
5046
|
+
table_id: Uuid;
|
|
5047
|
+
questions: unknown[];
|
|
5048
|
+
values: Record<string, unknown>;
|
|
5049
|
+
}): Promise<RecordsResult<Array<{
|
|
5050
|
+
field_key: string;
|
|
5051
|
+
asked: boolean;
|
|
5052
|
+
decided: boolean;
|
|
5053
|
+
said: string | null;
|
|
5054
|
+
}>>>;
|
|
5055
|
+
/**
|
|
5056
|
+
* WHAT A FORM'S LOOK MAY BE, AND WHAT IT WOULD LOOK LIKE (`custom.form_look_options`): the
|
|
5057
|
+
* organization's public pictures (the same list a portal's look offers), the colours, and the
|
|
5058
|
+
* look a stranger would see for the draft `presentation` — the builder's preview draws that.
|
|
5059
|
+
*/
|
|
5060
|
+
formLookOptions(args?: {
|
|
5061
|
+
presentation?: Record<string, unknown> | null;
|
|
5062
|
+
}): Promise<RecordsResult<FormLookOptions>>;
|
|
5063
|
+
/**
|
|
5064
|
+
* THE ROUTE THROUGH A DRAFT FORM (`custom.form_preview_route`, lane TYPEFORM-DUP): which questions
|
|
5065
|
+
* are asked given the answers so far (showIf AND logic jumps), the ending reached and the score —
|
|
5066
|
+
* the store's walk, the one the stranger's page and `custom.form_submit` read too.
|
|
5067
|
+
*/
|
|
5068
|
+
formPreviewRoute(args: {
|
|
5069
|
+
table_id: Uuid;
|
|
5070
|
+
questions: unknown[];
|
|
5071
|
+
endings?: unknown[] | null;
|
|
5072
|
+
values: Record<string, unknown>;
|
|
5073
|
+
}): Promise<RecordsResult<FormRoute>>;
|
|
5074
|
+
/** A form's results (`custom.form_results`): views, starts, completions, drop-off, answers. */
|
|
5075
|
+
formResults(args: {
|
|
5076
|
+
form_id: Uuid;
|
|
5077
|
+
}): Promise<RecordsResult<FormResults>>;
|
|
5078
|
+
/** TYPEFORM-2: the organization's form knobs (`custom.form_knobs`): owner header, choice auto-advance. */
|
|
5079
|
+
formKnobs(): Promise<RecordsResult<{
|
|
5080
|
+
show_owner_header: boolean;
|
|
5081
|
+
choice_auto_advance: boolean;
|
|
5082
|
+
}>>;
|
|
5083
|
+
/**
|
|
5084
|
+
* What the store makes of a file's columns, before anything is written.
|
|
5085
|
+
* `columns` is `[{header, samples}]` — the first page of the file is plenty.
|
|
5086
|
+
*/
|
|
5087
|
+
importPlan(args: {
|
|
5088
|
+
table_id: Uuid;
|
|
5089
|
+
columns: Array<{
|
|
5090
|
+
header: string;
|
|
5091
|
+
samples: unknown[];
|
|
5092
|
+
}>;
|
|
5093
|
+
}): Promise<RecordsResult<ImportPlan>>;
|
|
5094
|
+
/**
|
|
5095
|
+
* Open a run. `file_hash` is the run's IDENTITY: the same bytes into the same
|
|
5096
|
+
* table a second time answer the FIRST run with `already: true` and write
|
|
5097
|
+
* nothing, so a re-import doubles nothing. `force` re-opens deliberately.
|
|
5098
|
+
*/
|
|
5099
|
+
importBegin(args: {
|
|
5100
|
+
table_id: Uuid;
|
|
5101
|
+
format?: "csv" | "xlsx";
|
|
5102
|
+
source_name?: string | null;
|
|
5103
|
+
source_columns?: unknown[];
|
|
5104
|
+
file_hash?: string | null;
|
|
5105
|
+
policy?: ImportPolicy;
|
|
5106
|
+
/** A Field key. A row whose value for it is already here is a duplicate. */
|
|
5107
|
+
dedupe_key?: string | null;
|
|
5108
|
+
file_bytes?: number | null;
|
|
5109
|
+
force?: boolean;
|
|
5110
|
+
}): Promise<RecordsResult<ImportOpened>>;
|
|
5111
|
+
/**
|
|
5112
|
+
* IMPORT-2. ADD THE COLUMNS THIS FILE HAS AND THIS TABLE HAS NOT — a step of
|
|
5113
|
+
* its own, BEFORE the run is opened, so the screen can show "8 columns added"
|
|
5114
|
+
* and the person can then name one of them as the file's duplicate key
|
|
5115
|
+
* (`importBegin` refuses a key naming a column that does not exist yet).
|
|
5116
|
+
* Answers the mapping the file should be sent with. Admin on the Table.
|
|
5117
|
+
*/
|
|
5118
|
+
importDeclareColumns(args: {
|
|
5119
|
+
table_id: Uuid;
|
|
5120
|
+
rows: Array<Record<string, unknown>>;
|
|
5121
|
+
/** Header -> Field key the person already mapped by hand; never declared. */
|
|
5122
|
+
mapping?: Record<string, string>;
|
|
5123
|
+
}): Promise<RecordsResult<ImportColumnsDeclared>>;
|
|
5124
|
+
/**
|
|
5125
|
+
* One BATCH of rows. The batch is PLANNED and then written as ONE statement
|
|
5126
|
+
* through the batched write door, so 250 round trips became one; a batch a
|
|
5127
|
+
* guard refuses falls back to one write a row, and the answer says which it
|
|
5128
|
+
* was. Send `ImportOpened.rows_per_call` the first time and
|
|
5129
|
+
* `ImportBatchResult.rows_per_call` — measured — every time after that.
|
|
5130
|
+
*/
|
|
5131
|
+
importRows(args: {
|
|
5132
|
+
import_id: Uuid;
|
|
5133
|
+
rows: Array<Record<string, unknown>>;
|
|
5134
|
+
/** Header -> Field key. A header that already spells a key needs no entry. */
|
|
5135
|
+
mapping?: Record<string, string>;
|
|
5136
|
+
}): Promise<RecordsResult<ImportBatchResult>>;
|
|
5137
|
+
/**
|
|
5138
|
+
* Close the run and decide the columns the file had and the table did not:
|
|
5139
|
+
* `propose` (the ONE approvals inbox, and the only choice a non-admin has),
|
|
5140
|
+
* `create` (an admin adds them outright) or `ignore`.
|
|
5141
|
+
*/
|
|
5142
|
+
importFinish(args: {
|
|
5143
|
+
import_id: Uuid;
|
|
5144
|
+
unmapped?: "propose" | "create" | "ignore";
|
|
5145
|
+
}): Promise<RecordsResult<ImportFinished>>;
|
|
5146
|
+
/** The refused rows, or the ones already here, WITH the source row on each. */
|
|
5147
|
+
importReport(args: {
|
|
5148
|
+
import_id: Uuid;
|
|
5149
|
+
state?: "refused" | "duplicate";
|
|
5150
|
+
limit?: number;
|
|
5151
|
+
offset?: number;
|
|
5152
|
+
}): Promise<RecordsResult<ImportReport>>;
|
|
5153
|
+
/** This organization's import runs, newest first. How you find yesterday's. */
|
|
5154
|
+
imports(args?: {
|
|
5155
|
+
table_id?: Uuid | null;
|
|
5156
|
+
limit?: number;
|
|
5157
|
+
}): Promise<RecordsResult<ImportRun[]>>;
|
|
5158
|
+
/**
|
|
5159
|
+
* Forget the RECEIPT for a file so the same bytes can be imported again
|
|
5160
|
+
* deliberately. Never touches the records that import wrote.
|
|
5161
|
+
*/
|
|
5162
|
+
importForget(args: {
|
|
5163
|
+
import_id: Uuid;
|
|
5164
|
+
}): Promise<RecordsResult<boolean>>;
|
|
5165
|
+
/**
|
|
5166
|
+
* Give a table its own address. The answer carries `mail_route`: the one
|
|
5167
|
+
* sentence saying what has to exist in DNS before anything arrives. Show it
|
|
5168
|
+
* wherever the address is shown — an address that silently swallows mail is
|
|
5169
|
+
* the failure this whole door is against.
|
|
5170
|
+
*/
|
|
5171
|
+
inboundDeclare(args: {
|
|
5172
|
+
table_id: Uuid;
|
|
5173
|
+
label?: string | null;
|
|
5174
|
+
}): Promise<RecordsResult<InboundDeclared>>;
|
|
5175
|
+
inboundAddresses(args?: {
|
|
5176
|
+
table_id?: Uuid | null;
|
|
5177
|
+
}): Promise<RecordsResult<InboundAddress[]>>;
|
|
5178
|
+
inboundSet(args: {
|
|
5179
|
+
inbound_id: Uuid;
|
|
5180
|
+
enabled: boolean;
|
|
5181
|
+
}): Promise<RecordsResult<{
|
|
5182
|
+
inbound_id: Uuid;
|
|
5183
|
+
address: string;
|
|
5184
|
+
enabled: boolean;
|
|
5185
|
+
message: string;
|
|
5186
|
+
}>>;
|
|
5187
|
+
/** Every portal over this organization the caller may know about, with its numbers. */
|
|
5188
|
+
portals(): Promise<RecordsResult<PortalSummary[]>>;
|
|
5189
|
+
/**
|
|
5190
|
+
* The SAME list, archive-aware. `custom.portals` keeps its signature and hides
|
|
5191
|
+
* archived portals, because the archived-items law's default is to hide;
|
|
5192
|
+
* this is the one door that also answers the other lane, so a rail gets the
|
|
5193
|
+
* law's one-click reveal without inventing a second control or a second door.
|
|
5194
|
+
* A fourth word is refused `22023` — there is no fourth answer on any surface.
|
|
5195
|
+
*/
|
|
5196
|
+
listPortals(args?: {
|
|
5197
|
+
archived?: PortalArchiveFilter;
|
|
5198
|
+
}): Promise<RecordsResult<PortalSummary[]>>;
|
|
5199
|
+
/**
|
|
5200
|
+
* PUT ONE PORTAL AWAY. Nothing is deleted and there is no purge: every Table
|
|
5201
|
+
* it exposes and every person invited to it is kept exactly as it is, and
|
|
5202
|
+
* `portalRestore` hands it all back. `confirm_title` is the portal's own title
|
|
5203
|
+
* typed back — ten portals can carry one title, so the title is not what picks
|
|
5204
|
+
* this one and the door refuses `23514` when it does not match.
|
|
5205
|
+
*/
|
|
5206
|
+
portalArchive(args: {
|
|
5207
|
+
portal_id: Uuid;
|
|
5208
|
+
confirm_title: string;
|
|
5209
|
+
reason?: string | null;
|
|
5210
|
+
}): Promise<RecordsResult<PortalArchiveAnswer>>;
|
|
5211
|
+
/** The way back. Everyone invited signs in exactly as before, and it shows the same Tables. */
|
|
5212
|
+
portalRestore(args: {
|
|
5213
|
+
portal_id: Uuid;
|
|
5214
|
+
confirm_title: string;
|
|
5215
|
+
}): Promise<RecordsResult<PortalArchiveAnswer>>;
|
|
5216
|
+
/**
|
|
5217
|
+
* PUT ONE FORM OR BOOKING PAGE AWAY (`custom.form_archive`, admin on its table). Its address stops
|
|
5218
|
+
* answering; everything it collected is kept. `formRestore` brings it back.
|
|
5219
|
+
*/
|
|
5220
|
+
formArchive(args: {
|
|
5221
|
+
form_id: Uuid;
|
|
5222
|
+
}): Promise<RecordsResult<FormArchiveAnswer>>;
|
|
5223
|
+
formRestore(args: {
|
|
5224
|
+
form_id: Uuid;
|
|
5225
|
+
}): Promise<RecordsResult<FormArchiveAnswer>>;
|
|
5226
|
+
/** The archived forms and booking pages, newest first; `table_id` narrows to one table. */
|
|
5227
|
+
formsArchived(args?: {
|
|
5228
|
+
table_id?: Uuid | null;
|
|
5229
|
+
limit?: number;
|
|
5230
|
+
}): Promise<RecordsResult<ArchivedForm[]>>;
|
|
5231
|
+
/**
|
|
5232
|
+
* The archived checklist templates. A template is a record: `recordDelete` archives it and
|
|
5233
|
+
* `recordRestore` brings it back.
|
|
5234
|
+
*/
|
|
5235
|
+
checklistTemplatesArchived(args?: {
|
|
5236
|
+
about_table_id?: Uuid | null;
|
|
5237
|
+
limit?: number;
|
|
5238
|
+
}): Promise<RecordsResult<ArchivedChecklistTemplate[]>>;
|
|
5239
|
+
/** What a table's NEW rows start with (Shown to, and the web half once it lands). */
|
|
5240
|
+
tableRowDefaults(args: {
|
|
5241
|
+
table_id: Uuid;
|
|
5242
|
+
}): Promise<RecordsResult<TableRowDefaults>>;
|
|
5243
|
+
/** Set them (the table's maker or an admin of it). A key left out is left alone; null = the default. */
|
|
5244
|
+
tableRowDefaultsSet(args: {
|
|
5245
|
+
table_id: Uuid;
|
|
5246
|
+
defaults: TableRowDefaultsPatch;
|
|
5247
|
+
}): Promise<RecordsResult<TableRowDefaults>>;
|
|
5248
|
+
/**
|
|
5249
|
+
* ONE PASS of "apply to existing rows": rows nobody set by hand follow the table's defaults.
|
|
5250
|
+
* `done: false` → call again with `after: next_after`. `rowDefaultsApplyAll` walks every pass.
|
|
5251
|
+
*/
|
|
5252
|
+
tableRowDefaultsApply(args: {
|
|
5253
|
+
table_id: Uuid;
|
|
5254
|
+
after?: Uuid | null;
|
|
5255
|
+
}): Promise<RecordsResult<RowDefaultsApplied>>;
|
|
5256
|
+
/** Every pass of `tableRowDefaultsApply`, summed; the last pass's sentence when it took one pass. */
|
|
5257
|
+
rowDefaultsApplyAll(args: {
|
|
5258
|
+
table_id: Uuid;
|
|
5259
|
+
maxPasses?: number;
|
|
5260
|
+
}): Promise<RecordsResult<RowDefaultsApplied>>;
|
|
5261
|
+
/** One row's Shown to (and web half), with who may change it. */
|
|
5262
|
+
recordRowControls(args: {
|
|
5263
|
+
record_id: Uuid;
|
|
5264
|
+
}): Promise<RecordsResult<RecordRowControls>>;
|
|
5265
|
+
recordRowControlsSet(args: {
|
|
5266
|
+
record_id: Uuid;
|
|
5267
|
+
controls: {
|
|
5268
|
+
shown_to?: string | null;
|
|
5269
|
+
published_to_web?: boolean;
|
|
5270
|
+
indexed?: boolean | null;
|
|
5271
|
+
};
|
|
5272
|
+
}): Promise<RecordsResult<RecordRowControls>>;
|
|
5273
|
+
/**
|
|
5274
|
+
* Which Tables each portal of this organization exposes.
|
|
5275
|
+
*
|
|
5276
|
+
* The one question a TABLE-scoped Portals rail has to ask: "is the table I
|
|
5277
|
+
* am standing on in any portal?" Same wall and same read-access gate as
|
|
5278
|
+
* `portals`, so a pair here is always a portal `portals` also returned.
|
|
5279
|
+
*/
|
|
5280
|
+
portalTables(): Promise<RecordsResult<PortalTableRef[]>>;
|
|
5281
|
+
/** ONE portal in full: what it shows, and who it was opened to. */
|
|
5282
|
+
portalCard(args: {
|
|
5283
|
+
portal_id: Uuid;
|
|
5284
|
+
}): Promise<RecordsResult<PortalCard>>;
|
|
5285
|
+
/**
|
|
5286
|
+
* Create or RE-STATE one portal. Re-stating REPLACES what it exposes — a
|
|
5287
|
+
* Table left out of `tables` stops being exposed in the same act — and leaves
|
|
5288
|
+
* the people alone: who is invited is not part of what the portal shows.
|
|
5289
|
+
*/
|
|
5290
|
+
portalDeclare(args: {
|
|
5291
|
+
title: string;
|
|
5292
|
+
client_table_id: Uuid;
|
|
5293
|
+
tables: Array<{
|
|
5294
|
+
table_id: Uuid;
|
|
5295
|
+
names_via: string;
|
|
5296
|
+
visible_fields?: string[];
|
|
5297
|
+
editable_fields?: string[];
|
|
5298
|
+
comments?: boolean;
|
|
5299
|
+
}>;
|
|
5300
|
+
portal_id?: Uuid | null;
|
|
5301
|
+
slug?: string | null;
|
|
5302
|
+
sign_in_method?: string | null;
|
|
5303
|
+
/**
|
|
5304
|
+
* S6 — the portal's own look and its forms. A key given REPLACES that key; a key not given
|
|
5305
|
+
* is KEPT (leave `config` out and both stay exactly as they are). The store judges it and
|
|
5306
|
+
* refuses by name: a logo that is not a public picture of this organization's Files, an
|
|
5307
|
+
* accent that is not a design-system colour name, a form whose Table the portal does not show.
|
|
5308
|
+
*/
|
|
5309
|
+
config?: PortalConfigInput | null;
|
|
5310
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5311
|
+
/**
|
|
5312
|
+
* S6 — THE CLIENT'S SIDE: one form of HER portal (`custom.portal_form`). Refused unless the
|
|
5313
|
+
* caller is a live principal of that live portal and the form is on its list; the Field that
|
|
5314
|
+
* names the client is never one of the questions — the portal fills it.
|
|
5315
|
+
*/
|
|
5316
|
+
portalForm(args: {
|
|
5317
|
+
portal_id: Uuid;
|
|
5318
|
+
form_id: Uuid;
|
|
5319
|
+
}): Promise<RecordsResult<PortalFormSpec>>;
|
|
5320
|
+
/**
|
|
5321
|
+
* S6 — send one form of her portal (`custom.portal_form_submit`). The store fills the Field
|
|
5322
|
+
* that names the client with her own record, and the answer reaches her own list at once
|
|
5323
|
+
* (`accepted`) or waits for the office (`held`, with the store's sentence). `client_key`
|
|
5324
|
+
* makes a retry the same submission.
|
|
5325
|
+
*/
|
|
5326
|
+
portalFormSubmit(args: {
|
|
5327
|
+
portal_id: Uuid;
|
|
5328
|
+
form_id: Uuid;
|
|
5329
|
+
answers: Record<string, unknown>;
|
|
5330
|
+
client_key?: string | null;
|
|
5331
|
+
}): Promise<RecordsResult<PortalFormAnswer>>;
|
|
5332
|
+
/**
|
|
5333
|
+
* Invite one person, as one record of the portal's client Table.
|
|
5334
|
+
*
|
|
5335
|
+
* `user_id` is deliberately NOT a parameter here. From a screen it is always
|
|
5336
|
+
* null: an invitation confers NOTHING until the person follows their sign-in
|
|
5337
|
+
* link and the platform gives them an identity, and the door's own `say`
|
|
5338
|
+
* sentence states exactly that. A screen that passed an id would be granting
|
|
5339
|
+
* access on somebody else's behalf.
|
|
5340
|
+
*/
|
|
5341
|
+
portalInvite(args: {
|
|
5342
|
+
portal_id: Uuid;
|
|
5343
|
+
client_record_id: Uuid;
|
|
5344
|
+
email: string;
|
|
5345
|
+
}): Promise<RecordsResult<PortalInvitation>>;
|
|
5346
|
+
/** Take one person's way in away. The answer's `say` names the consequence. */
|
|
5347
|
+
portalRevoke(args: {
|
|
5348
|
+
portal_id: Uuid;
|
|
5349
|
+
principal_id: Uuid;
|
|
5350
|
+
}): Promise<RecordsResult<PortalRevocation>>;
|
|
5351
|
+
/**
|
|
5352
|
+
* VIEW AS THIS CLIENT. The door asks `custom.visible_set` for HER user id —
|
|
5353
|
+
* the same call `custom.read_records` makes when she opens the page — so this
|
|
5354
|
+
* cannot disagree with what she sees. It REFUSES with `02000` and a sentence
|
|
5355
|
+
* when she has not signed in yet; show the sentence, never an empty list.
|
|
5356
|
+
*/
|
|
5357
|
+
portalPreview(args: {
|
|
5358
|
+
portal_id: Uuid;
|
|
5359
|
+
principal_id: Uuid;
|
|
5360
|
+
table_id: Uuid;
|
|
5361
|
+
}): Promise<RecordsResult<PortalPreviewRow[]>>;
|
|
5362
|
+
/** This organization's dashboards, optionally only those whose subject is one Table. */
|
|
5363
|
+
dashboards(args?: {
|
|
5364
|
+
table_id?: Uuid | null;
|
|
5365
|
+
}): Promise<RecordsResult<DashboardSummary[]>>;
|
|
5366
|
+
/**
|
|
5367
|
+
* Create or re-state one dashboard. Every block is judged on the way IN —
|
|
5368
|
+
* a block naming a field this Table does not have is refused BY NAME, with
|
|
5369
|
+
* the table's own field list in the hint — so a canvas cannot be saved broken.
|
|
5370
|
+
*/
|
|
5371
|
+
dashboardDeclare(args: {
|
|
5372
|
+
table_id: Uuid;
|
|
5373
|
+
name: string;
|
|
5374
|
+
blocks?: DashboardBlock[];
|
|
5375
|
+
presentation?: Record<string, unknown> | null;
|
|
5376
|
+
dashboard_id?: Uuid | null;
|
|
5377
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5378
|
+
/**
|
|
5379
|
+
* Run every block and answer the numbers. `filter` is the ONE filter bar
|
|
5380
|
+
* across the canvas: it is merged UNDER each block's own filter, so a block
|
|
5381
|
+
* deliberately scoped to one stage stays scoped while the bar moves the rest.
|
|
5382
|
+
* A block that refuses carries the store's sentence and the others still answer.
|
|
5383
|
+
*/
|
|
5384
|
+
dashboardRun(args: {
|
|
5385
|
+
dashboard_id: Uuid;
|
|
5386
|
+
filter?: RecordFilter;
|
|
5387
|
+
/**
|
|
5388
|
+
* S3 — compare every block that does not carry its own comparison (the
|
|
5389
|
+
* block's own wins, as its own filter does). A block with no date to
|
|
5390
|
+
* compare along answers alone and says so in `compare_refused`.
|
|
5391
|
+
*/
|
|
5392
|
+
compare?: AggregateCompare | null;
|
|
5393
|
+
/** S3 — re-cut every bucketed block to one date grain (the canvas's picker). */
|
|
5394
|
+
grain?: AggregateBucket | null;
|
|
5395
|
+
}): Promise<RecordsResult<DashboardRunResult>>;
|
|
5396
|
+
/** The seventh block kind on its own: records that have sat on the same value too long. */
|
|
5397
|
+
dashboardStuck(args: {
|
|
5398
|
+
table_id: Uuid;
|
|
5399
|
+
state_key: string;
|
|
5400
|
+
days?: number;
|
|
5401
|
+
filter?: RecordFilter;
|
|
5402
|
+
limit?: number;
|
|
5403
|
+
}): Promise<RecordsResult<StuckRow[]>>;
|
|
5404
|
+
/**
|
|
5405
|
+
* Declare or re-state a crew capture sheet over a Table. Admin on the Table.
|
|
5406
|
+
* Closed to the crew until `capturePublish`, like every publishing act here.
|
|
5407
|
+
*/
|
|
5408
|
+
captureSheetDeclare(args: {
|
|
5409
|
+
table_id: Uuid;
|
|
5410
|
+
title: string;
|
|
5411
|
+
questions: Array<Record<string, unknown>>;
|
|
5412
|
+
presentation?: Record<string, unknown> | null;
|
|
5413
|
+
sheet_id?: Uuid | null;
|
|
5414
|
+
notify_rule_id?: Uuid | null;
|
|
5415
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5416
|
+
/** Open the sheet to the crew, or close it. Admin on the Table. */
|
|
5417
|
+
capturePublish(args: {
|
|
5418
|
+
sheet_id: Uuid;
|
|
5419
|
+
open?: boolean;
|
|
5420
|
+
}): Promise<RecordsResult<string | null>>;
|
|
5421
|
+
/** The crew sheets of this organization, with what has come in through each. */
|
|
5422
|
+
captureSheets(args?: {
|
|
5423
|
+
table_id?: Uuid | null;
|
|
5424
|
+
}): Promise<RecordsResult<CaptureSheetSummary[]>>;
|
|
5425
|
+
/**
|
|
5426
|
+
* Everything a phone needs to run one sheet OFFLINE — the questions, the Fields
|
|
5427
|
+
* with their ids and parity types, and an honest `may_capture` with a sentence.
|
|
5428
|
+
* Load it once on a signal; it is the last network call before the walk.
|
|
5429
|
+
*/
|
|
5430
|
+
captureOpen(args: {
|
|
5431
|
+
sheet_id: Uuid;
|
|
5432
|
+
}): Promise<RecordsResult<CaptureSheetFace | null>>;
|
|
5433
|
+
/**
|
|
5434
|
+
* One capture: the answers, the file references, the device, the moment the phone
|
|
5435
|
+
* took it and the place. Idempotent on `client_key`, which the PHONE mints when
|
|
5436
|
+
* the capture is taken, offline, before its first attempt — send the same key on
|
|
5437
|
+
* every retry and the answer comes back `replay: true` with the first record's id.
|
|
5438
|
+
*/
|
|
5439
|
+
captureSubmit(args: {
|
|
5440
|
+
sheet_id: Uuid;
|
|
5441
|
+
client_key: string;
|
|
5442
|
+
answers: Record<string, unknown>;
|
|
5443
|
+
files?: CaptureFileRef[];
|
|
5444
|
+
device?: string | null;
|
|
5445
|
+
captured_at?: string | null;
|
|
5446
|
+
location?: Record<string, unknown> | null;
|
|
5447
|
+
}): Promise<RecordsResult<CaptureOutcome | null>>;
|
|
5448
|
+
/** Every agent-owned column, with how many cells are filled, stale or pinned, and what it has cost. */
|
|
5449
|
+
enrichments(args?: {
|
|
5450
|
+
table_id?: Uuid | null;
|
|
5451
|
+
}): Promise<RecordsResult<EnrichmentSummary[]>>;
|
|
5452
|
+
/**
|
|
5453
|
+
* Define, change or TURN ON an Enrichment on one Field. Admin on the Table.
|
|
5454
|
+
* `{enabled: true}` on its own turns an existing one on without resetting it —
|
|
5455
|
+
* and turning it on is what authorises every value it writes afterwards.
|
|
5456
|
+
*/
|
|
5457
|
+
enrichDeclare(args: {
|
|
5458
|
+
field_id: Uuid;
|
|
5459
|
+
spec: Record<string, unknown>;
|
|
5460
|
+
}): Promise<RecordsResult<EnrichDeclared>>;
|
|
5461
|
+
/**
|
|
5462
|
+
* The rows that need this column filled in, each with what the instruction may
|
|
5463
|
+
* read. A cell somebody pinned is never returned. This is what a PREVIEW shows
|
|
5464
|
+
* before anybody enables anything.
|
|
5465
|
+
*/
|
|
5466
|
+
enrichDue(args: {
|
|
5467
|
+
field_id: Uuid;
|
|
5468
|
+
limit?: number;
|
|
5469
|
+
include_fresh?: boolean;
|
|
5470
|
+
}): Promise<RecordsResult<EnrichDueRow[]>>;
|
|
5471
|
+
/**
|
|
5472
|
+
* THE BADGE DATA FOR A WHOLE PAGE, in one call. Who wrote each value, when, out
|
|
5473
|
+
* of what source, its candidates, whether a person pinned it and whether it is
|
|
5474
|
+
* past its freshness date. Asked per cell this would be one round trip per badge.
|
|
5475
|
+
*/
|
|
5476
|
+
enrichCells(args: {
|
|
5477
|
+
table_id: Uuid;
|
|
5478
|
+
field_keys?: string[] | null;
|
|
5479
|
+
record_ids?: Uuid[] | null;
|
|
5480
|
+
}): Promise<RecordsResult<EnrichCell[]>>;
|
|
5481
|
+
/** Hold one cell against the model that fills its column, or hand it back. */
|
|
5482
|
+
enrichPin(args: {
|
|
5483
|
+
record_id: Uuid;
|
|
5484
|
+
field_key: string;
|
|
5485
|
+
pinned?: boolean;
|
|
5486
|
+
}): Promise<RecordsResult<{
|
|
5487
|
+
pinned: boolean;
|
|
5488
|
+
says: string;
|
|
5489
|
+
}>>;
|
|
5490
|
+
/** What this column has cost, run by run. */
|
|
5491
|
+
enrichRuns(args?: {
|
|
5492
|
+
field_id?: Uuid | null;
|
|
5493
|
+
limit?: number;
|
|
5494
|
+
}): Promise<RecordsResult<EnrichRun[]>>;
|
|
5495
|
+
/** Take a dashboard away. The records it counted are untouched — a canvas owns nothing. */
|
|
5496
|
+
dashboardDelete(args: {
|
|
5497
|
+
dashboard_id: Uuid;
|
|
5498
|
+
}): Promise<RecordsResult<boolean>>;
|
|
5499
|
+
/**
|
|
5500
|
+
* Group, bucket, filter and measure INSIDE `custom.record_aggregate`. The
|
|
5501
|
+
* aggregate node sits above the read-access join, so what a chart draws is
|
|
5502
|
+
* exactly what this person may see — the rest is never fetched, let alone
|
|
5503
|
+
* summed and then hidden.
|
|
5504
|
+
*/
|
|
5505
|
+
recordAggregate(args: {
|
|
5506
|
+
table_id: Uuid;
|
|
5507
|
+
/**
|
|
5508
|
+
* OPTIONAL FILTER (active-org law): with `config.organizationIds` set, the table is looked
|
|
5509
|
+
* up across all the person's organizations and the aggregate runs in the one that OWNS it
|
|
5510
|
+
* (each row then carries that `organization_id`); this narrows the lookup to one. Absent and
|
|
5511
|
+
* no `organizationIds` ⇒ this client's own organization, exactly as before.
|
|
5512
|
+
*/
|
|
5513
|
+
organization_id?: Uuid | null;
|
|
5514
|
+
/** Field keys whose values become the groups. */
|
|
5515
|
+
groupBy?: string[];
|
|
5516
|
+
/** `count` needs no key; every other operation reads one Field. */
|
|
5517
|
+
measures?: AggregateMeasure[];
|
|
5518
|
+
/** A date Field truncated to a period — a group whose expression is a date_trunc. */
|
|
5519
|
+
bucket?: {
|
|
5520
|
+
key: string;
|
|
5521
|
+
by: AggregateBucket;
|
|
5522
|
+
} | null;
|
|
5523
|
+
/**
|
|
5524
|
+
* A scalar is an equality and an object is a half-open moment window, and
|
|
5525
|
+
* either way it lands in the SAME WHERE as read access.
|
|
5526
|
+
*/
|
|
5527
|
+
filter?: StoreFilter;
|
|
5528
|
+
limit?: number;
|
|
5529
|
+
/**
|
|
5530
|
+
* S3 — answer the same question over a prior window too (previous period,
|
|
5531
|
+
* same period last year, or a fixed baseline). Each row then carries
|
|
5532
|
+
* `prior_measures`, `delta` and the two `compare` windows. Buckets are cut
|
|
5533
|
+
* in the organization's calendar (knobs `custom/time_zone`, `custom/week_start`).
|
|
5534
|
+
*/
|
|
5535
|
+
compare?: AggregateCompare | null;
|
|
5536
|
+
/**
|
|
5537
|
+
* The grid's search, narrowing the answer to the rows `listPage`'s search would show (the
|
|
5538
|
+
* same predicate, `custom.record_search_sql`). Blank or absent: nothing changes.
|
|
5539
|
+
*/
|
|
5540
|
+
search?: string | null;
|
|
5541
|
+
/** The reader's time zone for the search's date matches (absent = the organization's calendar). */
|
|
5542
|
+
time_zone?: string | null;
|
|
5543
|
+
}): Promise<RecordsResult<AggregateRow[]>>;
|
|
5544
|
+
/** Historical aggregate computed by the store at its recorded-time read door. */
|
|
5545
|
+
recordAggregateAsOf(args: {
|
|
5546
|
+
table_id: Uuid;
|
|
5547
|
+
recorded_at: string;
|
|
5548
|
+
measure?: string;
|
|
5549
|
+
field_key?: string | null;
|
|
5550
|
+
group_by?: string | null;
|
|
5551
|
+
match?: Record<string, unknown>;
|
|
5552
|
+
}): Promise<RecordsResult<Array<{
|
|
5553
|
+
bucket: string | null;
|
|
5554
|
+
result: number | null;
|
|
5555
|
+
row_count: number;
|
|
5556
|
+
not_numbers: number;
|
|
5557
|
+
a_non_number: string | null;
|
|
5558
|
+
}>>>;
|
|
5559
|
+
/** The measures the store itself offers. Asked, never hardcoded in a picker. */
|
|
5560
|
+
aggOperations(): Promise<RecordsResult<string[]>>;
|
|
5561
|
+
/** The periods the store itself buckets by. */
|
|
5562
|
+
aggBuckets(): Promise<RecordsResult<string[]>>;
|
|
5563
|
+
/**
|
|
5564
|
+
* The organization's calendar (knobs `custom/time_zone`, `custom/week_start`), cut by the SAME door the
|
|
5565
|
+
* relative date filters and the chart buckets use. A calendar or timeline reads its first day of the week
|
|
5566
|
+
* from here, never from a constant of its own (lane NOTION-SMALL-4).
|
|
5567
|
+
*/
|
|
5568
|
+
aggCalendar(): Promise<RecordsResult<{
|
|
5569
|
+
time_zone: string;
|
|
5570
|
+
week_start: string;
|
|
5571
|
+
}>>;
|
|
5572
|
+
/**
|
|
5573
|
+
* A source's drill definition — its Dimensions, Measures, drill paths and first screen.
|
|
5574
|
+
* `{kind: "table", id}` is a custom Table; `{kind: "entity", token}` a standard table by its
|
|
5575
|
+
* registry token or a declared definition by its key.
|
|
5576
|
+
*/
|
|
5577
|
+
drillDescribe(args: {
|
|
5578
|
+
source: DrillSource;
|
|
5579
|
+
}): Promise<RecordsResult<DrillDefinition>>;
|
|
5580
|
+
/**
|
|
5581
|
+
* Ask a source a question: grouped, bucketed (day…year in the organization's calendar),
|
|
5582
|
+
* compared, pivoted. A standard table is counted AS THE PERSON (its own row security decides
|
|
5583
|
+
* every row); groups past the cap fold into one Other row and the total row says so.
|
|
5584
|
+
*/
|
|
5585
|
+
drillAsk(args: {
|
|
5586
|
+
source: DrillSource;
|
|
5587
|
+
question?: DrillQuestion;
|
|
5588
|
+
}): Promise<RecordsResult<DrillAnswer>>;
|
|
5589
|
+
/** The records behind a number, through the same filter, read as the person. */
|
|
5590
|
+
drillRows(args: {
|
|
5591
|
+
source: DrillSource;
|
|
5592
|
+
where?: DrillQuestion["where"];
|
|
5593
|
+
window?: DrillQuestion["window"];
|
|
5594
|
+
sort?: DrillQuestion["sort"];
|
|
5595
|
+
lane?: DrillQuestion["lane"];
|
|
5596
|
+
columns?: string[];
|
|
5597
|
+
limit?: number;
|
|
5598
|
+
offset?: number;
|
|
5599
|
+
/** The viewer's search term, asked of the door (`platform._drill_compile` reads `question.search`). */
|
|
5600
|
+
search?: string;
|
|
5601
|
+
}): Promise<RecordsResult<DrillRowsPage>>;
|
|
5602
|
+
/**
|
|
5603
|
+
* Every subscription in this organization, optionally narrowed to one saved
|
|
5604
|
+
* view or one cadence. There is no subscription table: each one is a Rule
|
|
5605
|
+
* record carrying a `subscription` block, so a subscription is readable,
|
|
5606
|
+
* historied and agent-writable like anything else.
|
|
5607
|
+
*/
|
|
5608
|
+
aggSubscriptions(args?: {
|
|
5609
|
+
saved_view_id?: Uuid | null;
|
|
5610
|
+
cadence?: string | null;
|
|
5611
|
+
}): Promise<RecordsResult<Subscription[]>>;
|
|
5612
|
+
/** The cadences the store itself offers. Asked, never hardcoded in a picker. */
|
|
5613
|
+
aggSubscriptionCadences(): Promise<RecordsResult<string[]>>;
|
|
5614
|
+
/**
|
|
5615
|
+
* The same cadences, through the door a PERSON may call.
|
|
5616
|
+
* `aggSubscriptionCadences` is the notifier's own and holds no client grant,
|
|
5617
|
+
* so a screen that asked for it was refused and fell back to a list typed
|
|
5618
|
+
* into the picker — which drifts from what the digest runner honours. This
|
|
5619
|
+
* one delegates to the same array, so there is exactly one list.
|
|
5620
|
+
*/
|
|
5621
|
+
subscriptionCadences(): Promise<RecordsResult<string[]>>;
|
|
5622
|
+
/**
|
|
5623
|
+
* WHAT THIS PERSON IS BEING TOLD ABOUT, and what they may switch off.
|
|
5624
|
+
*
|
|
5625
|
+
* Mine, plus anyone's over a Table I hold admin on — narrowed to Tables I can
|
|
5626
|
+
* already open, so the list never reveals one. `aggSubscriptions` above is the
|
|
5627
|
+
* NOTIFIER's reader and no client can call it; this is the owner's.
|
|
5628
|
+
*/
|
|
5629
|
+
subscriptions(args?: {
|
|
5630
|
+
table_id?: Uuid | null;
|
|
5631
|
+
}): Promise<RecordsResult<MySubscription[]>>;
|
|
5632
|
+
/**
|
|
5633
|
+
* Switch one on or off. Muting is honoured in ONE place — the reader every
|
|
5634
|
+
* consumer goes through — so a screen can never say a subscription is off
|
|
5635
|
+
* while it keeps firing.
|
|
5636
|
+
*/
|
|
5637
|
+
subscriptionMute(args: {
|
|
5638
|
+
rule_id: Uuid;
|
|
5639
|
+
muted: boolean;
|
|
5640
|
+
}): Promise<RecordsResult<boolean>>;
|
|
5641
|
+
/**
|
|
5642
|
+
* WRITE ONE. The store refuses a cadence no runner acts on, a channel this
|
|
5643
|
+
* platform does not send on and quiet hours nobody can parse — by name — then
|
|
5644
|
+
* declares the Rule through `rule_declare`, because a Rule written as a record
|
|
5645
|
+
* carries `data_class = 'record'` and every reader that goes looking for a Rule
|
|
5646
|
+
* steps straight past it (REC-72).
|
|
5647
|
+
*/
|
|
5648
|
+
subscriptionDeclare(args: {
|
|
5649
|
+
table_id: Uuid;
|
|
5650
|
+
spec: SubscriptionSpec;
|
|
5651
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5652
|
+
/**
|
|
5653
|
+
* SHOW ME ONE NOW. The summary this subscription would send at this moment, with
|
|
5654
|
+
* what entered, left and changed NAMED. It assembles only: nothing is delivered,
|
|
5655
|
+
* nothing is recorded and the watermark does not move.
|
|
5656
|
+
*/
|
|
5657
|
+
subscriptionPreview(args: {
|
|
5658
|
+
rule_id: Uuid;
|
|
5659
|
+
}): Promise<RecordsResult<DigestPreview>>;
|
|
5660
|
+
/**
|
|
5661
|
+
* THE SAVED VIEWS OF A TABLE — what a subscription may be written over. Narrowed
|
|
5662
|
+
* in SQL as the definer to Tables this caller can already open, so the list can
|
|
5663
|
+
* never reveal a Table.
|
|
5664
|
+
*/
|
|
5665
|
+
views(args?: {
|
|
5666
|
+
table_id?: Uuid | null;
|
|
5667
|
+
}): Promise<RecordsResult<SavedViewRow[]>>;
|
|
5668
|
+
/**
|
|
5669
|
+
* SAVE ONE VIEW. VIEWER on the Table, not editor: writing down a question about a
|
|
5670
|
+
* Table is not changing it, and requiring editor would mean the people who read a
|
|
5671
|
+
* Table could not subscribe to anything in it.
|
|
5672
|
+
*/
|
|
5673
|
+
viewDeclare(args: {
|
|
5674
|
+
table_id: Uuid;
|
|
5675
|
+
spec: SavedViewSpecIn;
|
|
5676
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5677
|
+
/** A Table's row templates ("New from template"). VIEWER on the Table. */
|
|
5678
|
+
rowTemplates(args: {
|
|
5679
|
+
table_id: Uuid;
|
|
5680
|
+
}): Promise<RecordsResult<RowTemplateRow[]>>;
|
|
5681
|
+
/**
|
|
5682
|
+
* SAVE ONE ROW TEMPLATE — `{name, values}` by Field key; the same name again changes it, and
|
|
5683
|
+
* `{template_id, archived: true}` archives it. EDITOR on the Table: it is how everyone's new rows start.
|
|
5684
|
+
*/
|
|
5685
|
+
rowTemplateDeclare(args: {
|
|
5686
|
+
table_id: Uuid;
|
|
5687
|
+
spec: {
|
|
5688
|
+
name?: string;
|
|
5689
|
+
values?: Record<string, unknown>;
|
|
5690
|
+
template_id?: Uuid;
|
|
5691
|
+
archived?: boolean;
|
|
5692
|
+
};
|
|
5693
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5694
|
+
/**
|
|
5695
|
+
* DESIGNATE HOW A TABLE OPENS — "Make this the default". EDITOR on the Table: the named view
|
|
5696
|
+
* becomes the table's only default and, when `layout` is given, that is the layout everyone opens
|
|
5697
|
+
* it in. A layout press never designates (`viewDeclare` refuses the default view's layout and
|
|
5698
|
+
* is_default by name — VIEW-SWITCH-NOT-DESIGNATION, VERIFIER-21).
|
|
5699
|
+
*/
|
|
5700
|
+
viewDesignate(args: {
|
|
5701
|
+
table_id: Uuid;
|
|
5702
|
+
view_id: Uuid;
|
|
5703
|
+
layout?: string | null;
|
|
5704
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5705
|
+
/**
|
|
5706
|
+
* ARCHIVE ONE SAVED VIEW (lane TABLE-ACTIONS, T3.5). The soft delete of the `platform.saved_view`
|
|
5707
|
+
* row behind it — `public.saved_view_archive('custom/records', id)`, which asks its own ladder
|
|
5708
|
+
* (the view's creator, or admin on the view) and clears a default it held. The records are
|
|
5709
|
+
* untouched. `null` when the view was already gone. `viewRestore` (or Trash) brings it back.
|
|
5710
|
+
*/
|
|
5711
|
+
viewArchive(args: {
|
|
5712
|
+
view_id: Uuid;
|
|
5713
|
+
}): Promise<RecordsResult<Record<string, unknown> | null>>;
|
|
5714
|
+
/** PUT AN ARCHIVED VIEW BACK — the platform's one restore door, `public.entity_undelete('platform_saved_view', id)`. */
|
|
5715
|
+
viewRestore(args: {
|
|
5716
|
+
view_id: Uuid;
|
|
5717
|
+
}): Promise<RecordsResult<boolean>>;
|
|
5718
|
+
/**
|
|
5719
|
+
* THE CALLER'S OWN LOOK AT EACH SAVED VIEW OF A TABLE — `{ "<view id>": { look, updated_at } }`.
|
|
5720
|
+
* A look is the view settings one person chose while looking (a board's grouping, a calendar's
|
|
5721
|
+
* date field, a sort, a filter, hidden columns, widths, the layout), kept for her alone until an
|
|
5722
|
+
* editor saves it onto the view with `viewDeclare` ("Save to view"). Viewer on the Table.
|
|
5723
|
+
*/
|
|
5724
|
+
viewLookRead(args: {
|
|
5725
|
+
table_id: Uuid;
|
|
5726
|
+
}): Promise<RecordsResult<Record<string, {
|
|
5727
|
+
look: Record<string, unknown>;
|
|
5728
|
+
updated_at: string;
|
|
5729
|
+
}>>>;
|
|
5730
|
+
/**
|
|
5731
|
+
* KEEP THE CALLER'S OWN LOOK AT ONE VIEW — the whole look, as definition keys (`group_field`,
|
|
5732
|
+
* `date_field`, `sorts`, `where`, `presentation`, `layout`, …; a key set to null hides the view's
|
|
5733
|
+
* own). `look: null` is "Reset to view". The shared view row is never written. Answers the look
|
|
5734
|
+
* as kept (null after a reset).
|
|
5735
|
+
*/
|
|
5736
|
+
viewLookSet(args: {
|
|
5737
|
+
table_id: Uuid;
|
|
5738
|
+
view_id: Uuid;
|
|
5739
|
+
look: Record<string, unknown> | null;
|
|
5740
|
+
}): Promise<RecordsResult<Record<string, unknown> | null>>;
|
|
5741
|
+
docTemplateSave(args: {
|
|
5742
|
+
table_id: Uuid;
|
|
5743
|
+
name: string;
|
|
5744
|
+
body: string;
|
|
5745
|
+
template_id?: Uuid | null;
|
|
5746
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5747
|
+
/** The body with every token resolved against one record. Read-only, no render row. */
|
|
5748
|
+
docRenderBody(args: {
|
|
5749
|
+
template_id: Uuid;
|
|
5750
|
+
record_id: Uuid;
|
|
5751
|
+
}): Promise<RecordsResult<string>>;
|
|
5752
|
+
/** Write the render — frozen bytes a signature can be checked against. */
|
|
5753
|
+
docRenderDocument(args: {
|
|
5754
|
+
template_id: Uuid;
|
|
5755
|
+
record_id: Uuid;
|
|
5756
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5757
|
+
/** Every token in a body, in order, with the Field id each one points at. */
|
|
5758
|
+
docTokens(args: {
|
|
5759
|
+
body: string;
|
|
5760
|
+
}): Promise<RecordsResult<DocToken[]>>;
|
|
5761
|
+
/** The tokens this Table cannot answer, each with the store's own reason. */
|
|
5762
|
+
docUnresolvedTokens(args: {
|
|
5763
|
+
table_id: Uuid;
|
|
5764
|
+
body: string;
|
|
5765
|
+
}): Promise<RecordsResult<DocUnresolvedToken[]>>;
|
|
5766
|
+
docSign(args: {
|
|
5767
|
+
render_id: Uuid;
|
|
5768
|
+
field_key: string;
|
|
5769
|
+
signer_name: string;
|
|
5770
|
+
signer_user_id?: Uuid | null;
|
|
5771
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5772
|
+
/**
|
|
5773
|
+
* One signature: the seal AND whether what was signed is still what is there.
|
|
5774
|
+
* The store answers both, in one call, never the screen. Viewer on the record.
|
|
5775
|
+
*/
|
|
5776
|
+
docSignatureRead(args: {
|
|
5777
|
+
signature_id: Uuid;
|
|
5778
|
+
}): Promise<RecordsResult<unknown>>;
|
|
5779
|
+
/** Every template that renders one Table. Viewer on the Table. */
|
|
5780
|
+
docTemplates(args: {
|
|
5781
|
+
table_id: Uuid;
|
|
5782
|
+
}): Promise<RecordsResult<DocTemplateRow[]>>;
|
|
5783
|
+
/**
|
|
5784
|
+
* Retire one template. EDITOR on the Table it renders, because a template is
|
|
5785
|
+
* that Table's wording. Documents already rendered keep their frozen bytes
|
|
5786
|
+
* and their seals, so this can never invalidate a signature.
|
|
5787
|
+
*/
|
|
5788
|
+
docTemplateDelete(args: {
|
|
5789
|
+
template_id: Uuid;
|
|
5790
|
+
}): Promise<RecordsResult<boolean>>;
|
|
5791
|
+
/** Every frozen render of one record, newest first. Viewer on the record. */
|
|
5792
|
+
docRenders(args: {
|
|
5793
|
+
record_id: Uuid;
|
|
5794
|
+
}): Promise<RecordsResult<DocRenderRow[]>>;
|
|
5795
|
+
/** Every signature on one record. Viewer on the record. */
|
|
5796
|
+
docSignatures(args: {
|
|
5797
|
+
record_id: Uuid;
|
|
5798
|
+
}): Promise<RecordsResult<DocSignatureRow[]>>;
|
|
5799
|
+
/**
|
|
5800
|
+
* DOOR-11. One record's revisions, newest first. The read door answers
|
|
5801
|
+
* documents and deliberately not versions, so a screen that wants to save
|
|
5802
|
+
* optimistically reads the version of the record it LOADED from here — for
|
|
5803
|
+
* the one record being edited, never for a list.
|
|
5804
|
+
*/
|
|
5805
|
+
revisions(args: {
|
|
5806
|
+
record_id: Uuid;
|
|
5807
|
+
}): Promise<RecordsResult<RecordRevision[]>>;
|
|
5808
|
+
/**
|
|
5809
|
+
* PRODUCTS row 4. One record's version list, newest first: who (a person, or
|
|
5810
|
+
* an agent AND the person it acted for), when, the operation in the word
|
|
5811
|
+
* somebody used, and every field that moved with its before, its after, the
|
|
5812
|
+
* Rule version that produced a derived value and its source pointer. Viewer
|
|
5813
|
+
* on the record — reading how something got to be the way it is is reading.
|
|
5814
|
+
*/
|
|
5815
|
+
recordHistory(args: {
|
|
5816
|
+
record_id: Uuid;
|
|
5817
|
+
limit?: number;
|
|
5818
|
+
offset?: number;
|
|
5819
|
+
}): Promise<RecordsResult<RecordHistoryEntry[]>>;
|
|
5820
|
+
/**
|
|
5821
|
+
* AGT-N-9 — EVERYTHING A CHAT OPENED ON THIS RECORD MAY KNOW, IN ONE ROUND TRIP.
|
|
5822
|
+
*
|
|
5823
|
+
* The Fields with their `(record, field, value version)` triples, the relations one hop
|
|
5824
|
+
* out, the history, the comments and the Table's other records — assembled INSIDE the
|
|
5825
|
+
* database, every piece through the read door, under this person's own field-level
|
|
5826
|
+
* security. A Field the store masks comes back in `withheld` with the store's own
|
|
5827
|
+
* sentence and no value; a Field the organization keeps out of conversations comes back
|
|
5828
|
+
* there too, saying which of the two it is.
|
|
5829
|
+
*/
|
|
5830
|
+
recordScopeContext(args: {
|
|
5831
|
+
record_id: Uuid;
|
|
5832
|
+
relations?: number;
|
|
5833
|
+
history?: number;
|
|
5834
|
+
siblings?: number;
|
|
5835
|
+
}): Promise<RecordsResult<RecordScopeContext>>;
|
|
5836
|
+
/** What is this conversation about? */
|
|
5837
|
+
conversationScope(args: {
|
|
5838
|
+
conversation_id: Uuid;
|
|
5839
|
+
}): Promise<RecordsResult<ConversationScope>>;
|
|
5840
|
+
/** Point a conversation at one record. Refused unless this person may open it. */
|
|
5841
|
+
conversationScopeBind(args: {
|
|
5842
|
+
conversation_id: Uuid;
|
|
5843
|
+
record_id: Uuid;
|
|
5844
|
+
}): Promise<RecordsResult<ConversationScope>>;
|
|
5845
|
+
/** This conversation is no longer about a particular record. */
|
|
5846
|
+
conversationScopeUnbind(args: {
|
|
5847
|
+
conversation_id: Uuid;
|
|
5848
|
+
}): Promise<RecordsResult<ConversationScope>>;
|
|
5849
|
+
/** The binding AND the context of a bound conversation, in one round trip. */
|
|
5850
|
+
conversationScopeContext(args: {
|
|
5851
|
+
conversation_id: Uuid;
|
|
5852
|
+
relations?: number;
|
|
5853
|
+
history?: number;
|
|
5854
|
+
siblings?: number;
|
|
5855
|
+
}): Promise<RecordsResult<ConversationScopeContext>>;
|
|
5856
|
+
/**
|
|
5857
|
+
* "Who changed the price on ANY record?" One column's history across a whole
|
|
5858
|
+
* Table, narrowed to the records this person may see by a predicate in the
|
|
5859
|
+
* same statement. A column that names no Field is refused BY NAME, never
|
|
5860
|
+
* answered empty.
|
|
5861
|
+
*/
|
|
5862
|
+
fieldHistory(args: {
|
|
5863
|
+
table_id: Uuid;
|
|
5864
|
+
field_key: string;
|
|
5865
|
+
limit?: number;
|
|
5866
|
+
offset?: number;
|
|
5867
|
+
record_id?: Uuid;
|
|
5868
|
+
}): Promise<RecordsResult<FieldHistoryEntry[]>>;
|
|
5869
|
+
/**
|
|
5870
|
+
* WHAT A RESTORE WOULD CHANGE, BEFORE IT DOES. Editor on the record: this is
|
|
5871
|
+
* the first half of an act, and somebody who may not perform it is not shown
|
|
5872
|
+
* its preview. Pass `field_key` for one column.
|
|
5873
|
+
*/
|
|
5874
|
+
restorePreview(args: {
|
|
5875
|
+
record_id: Uuid;
|
|
5876
|
+
version: number;
|
|
5877
|
+
field_key?: string;
|
|
5878
|
+
}): Promise<RecordsResult<RestorePreview>>;
|
|
5879
|
+
/** Put the whole record back to a version, as a NEW version. Editor. */
|
|
5880
|
+
restoreVersion(args: {
|
|
5881
|
+
record_id: Uuid;
|
|
5882
|
+
version: number;
|
|
5883
|
+
}): Promise<RecordsResult<RestoreResult>>;
|
|
5884
|
+
/** Put ONE column back to what it said at a version, as a NEW version (HIS-N-2). Editor. */
|
|
5885
|
+
valueRestore(args: {
|
|
5886
|
+
record_id: Uuid;
|
|
5887
|
+
field_key: string;
|
|
5888
|
+
version: number;
|
|
5889
|
+
}): Promise<RecordsResult<RestoreResult>>;
|
|
5890
|
+
/**
|
|
5891
|
+
* SCR-18. The record's comment thread with everybody named, plus what THIS
|
|
5892
|
+
* person may do in it — decided by the store, in the same call, so a screen
|
|
5893
|
+
* never draws a composer the write door will refuse.
|
|
5894
|
+
*/
|
|
5895
|
+
commentThread(args: {
|
|
5896
|
+
record_id: Uuid;
|
|
5897
|
+
include_resolved?: boolean;
|
|
5898
|
+
}): Promise<RecordsResult<CommentThreadRead>>;
|
|
5899
|
+
/**
|
|
5900
|
+
* Write a comment at the `commenter` rung, optionally naming people. A
|
|
5901
|
+
* mention is a reference and not a regex over the body: the ids come from the
|
|
5902
|
+
* picker and the store refuses one who is not in the organization, or who
|
|
5903
|
+
* cannot open the record — because that notification would be a dead end.
|
|
5904
|
+
*/
|
|
5905
|
+
commentWrite(args: {
|
|
5906
|
+
record_id: Uuid;
|
|
5907
|
+
body: string;
|
|
5908
|
+
field_key?: string;
|
|
5909
|
+
parent_comment_id?: Uuid;
|
|
5910
|
+
mentions?: Uuid[];
|
|
5911
|
+
}): Promise<RecordsResult<CommentWritten>>;
|
|
5912
|
+
/** Resolve (or re-open) a thread. `commenter` — resolution is not a delete. */
|
|
5913
|
+
commentResolve(args: {
|
|
5914
|
+
comment_id: Uuid;
|
|
5915
|
+
resolved?: boolean;
|
|
5916
|
+
}): Promise<RecordsResult<boolean>>;
|
|
5917
|
+
/**
|
|
5918
|
+
* Every value of one record WITH its envelope — its own version, who wrote
|
|
5919
|
+
* it, who they were acting for and when. The timeline IS the record (REC-19);
|
|
5920
|
+
* there is no second history table.
|
|
5921
|
+
*/
|
|
5922
|
+
recordValuesVersioned(args: {
|
|
5923
|
+
record_id: Uuid;
|
|
5924
|
+
organization_id?: Uuid | null;
|
|
5925
|
+
}): Promise<RecordsResult<ReadValue[]>>;
|
|
5926
|
+
/**
|
|
5927
|
+
* Metadata search across EVERY organization the person belongs to (`config.organizationIds`;
|
|
5928
|
+
* `organization_id` narrows to one): the Tables and Fields whose name, key, label or description
|
|
5929
|
+
* holds `text` (case-insensitive; structure, never rows). Each match is `{id, kind: "table" |
|
|
5930
|
+
* "field", name, description, organization_id}` (a Field adds `key`, `table_id`, `field_type`).
|
|
5931
|
+
* An organization whose read door refuses is listed in `unavailable` WITH its reason and
|
|
5932
|
+
* never hides the rest. Only when NO organization answers is the whole search a failure (the
|
|
5933
|
+
* first refusal).
|
|
5934
|
+
*/
|
|
5935
|
+
metadataSearch(args: {
|
|
5936
|
+
text: string;
|
|
5937
|
+
organization_id?: Uuid | null;
|
|
5938
|
+
}): Promise<RecordsResult<MetadataSearchAnswer>>;
|
|
5939
|
+
/**
|
|
5940
|
+
* WHICH of the person's organizations can this client use right now? Asks every organization
|
|
5941
|
+
* in scope (`organization_id` narrows to one) whether its record store is open, so a host can
|
|
5942
|
+
* say "organization X is unavailable: <reason>" instead of silently dropping it. Organization
|
|
5943
|
+
* order is the person's own, never completion order.
|
|
5944
|
+
*/
|
|
5945
|
+
organizationsOpen(args?: {
|
|
5946
|
+
organization_id?: Uuid | null;
|
|
5947
|
+
}): Promise<RecordsResult<OrganizationsOpenAnswer>>;
|
|
5948
|
+
/**
|
|
5949
|
+
* The organization that OWNS a table or record — the one a write to it must run in. A
|
|
5950
|
+
* `table_id` is looked up across all the person's organizations; a `record_id` is opened in its
|
|
5951
|
+
* own. `null` = found in none of them. Never a permission: the store's doors still decide.
|
|
5952
|
+
*/
|
|
5953
|
+
ownerOrganization(args: {
|
|
5954
|
+
table_id?: Uuid | null;
|
|
5955
|
+
record_id?: Uuid | null;
|
|
5956
|
+
organization_id?: Uuid | null;
|
|
5957
|
+
}): Promise<RecordsResult<Uuid | null>>;
|
|
5958
|
+
/**
|
|
5959
|
+
* Mint an embed token. `mode` is `read` OR `write` and never both — the store
|
|
5960
|
+
* refuses a token carrying two decisions. The secret comes back ONCE, because
|
|
5961
|
+
* only its digest is stored: a database read cannot produce a working token.
|
|
5962
|
+
* `allowedOrigins` is required and matched EXACTLY, so `example.com.evil.test`
|
|
5963
|
+
* fails a check that a suffix match would pass.
|
|
5964
|
+
*/
|
|
5965
|
+
anonTokenIssue(args: {
|
|
5966
|
+
mode: "read" | "write";
|
|
5967
|
+
allowedOrigins: string[];
|
|
5968
|
+
formId?: Uuid | null;
|
|
5969
|
+
savedViewId?: Uuid | null;
|
|
5970
|
+
recordId?: Uuid | null;
|
|
5971
|
+
expiresAt?: Timestamp | null;
|
|
5972
|
+
}): Promise<RecordsResult<{
|
|
5973
|
+
token_id: Uuid;
|
|
5974
|
+
secret: string;
|
|
5975
|
+
}>>;
|
|
5976
|
+
/** What a secret is good for, from an origin. The store's sentence when it is not. */
|
|
5977
|
+
anonTokenVerify(args: {
|
|
5978
|
+
secret: string;
|
|
5979
|
+
origin: string;
|
|
5980
|
+
requiredMode?: "read" | "write" | null;
|
|
5981
|
+
}): Promise<RecordsResult<AnonTokenBinding>>;
|
|
5982
|
+
anonTokenRevoke(args: {
|
|
5983
|
+
token_id: Uuid;
|
|
5984
|
+
}): Promise<RecordsResult<boolean>>;
|
|
5985
|
+
/**
|
|
5986
|
+
* A STRANGER'S WRITE. The token supplies the organization, so this call names
|
|
5987
|
+
* none — and what it produces is a QUARANTINED SUBMISSION, not a record:
|
|
5988
|
+
* `custom.record` is never touched here. `clientKey` makes a replay free and
|
|
5989
|
+
* idempotent, which is what lets a flaky phone retry safely.
|
|
5990
|
+
*/
|
|
5991
|
+
anonWrite(args: {
|
|
5992
|
+
secret: string;
|
|
5993
|
+
origin: string;
|
|
5994
|
+
payload: Record<string, unknown>;
|
|
5995
|
+
clientKey?: string | null;
|
|
5996
|
+
rawPayload?: Record<string, unknown>;
|
|
5997
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
5998
|
+
/**
|
|
5999
|
+
* SCR-30, and it is the SIGNED-IN offline path, not the stranger's. The client
|
|
6000
|
+
* mints `clientKey` BEFORE the first attempt, offline, and the store's own
|
|
6001
|
+
* replay ledger dedupes on it — so a reconnect that fires the same capture
|
|
6002
|
+
* thirty times writes one record and returns the same id every time.
|
|
6003
|
+
*/
|
|
6004
|
+
anonCapture(args: {
|
|
6005
|
+
table_id: Uuid;
|
|
6006
|
+
clientKey: string;
|
|
6007
|
+
payload: Record<string, unknown>;
|
|
6008
|
+
device?: string | null;
|
|
6009
|
+
capturedAt?: Timestamp | null;
|
|
6010
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
6011
|
+
/** Open or close a form to strangers. An admin act on the Table, never an editor one. */
|
|
6012
|
+
anonPublish(args: {
|
|
6013
|
+
form_id: Uuid;
|
|
6014
|
+
published?: boolean;
|
|
6015
|
+
}): Promise<RecordsResult<Timestamp | null>>;
|
|
6016
|
+
/**
|
|
6017
|
+
* What is wrong with a checklist somebody is writing, in the words they would
|
|
6018
|
+
* use. `null` means it is fine. Pure — it reads no row and writes nothing —
|
|
6019
|
+
* so an editor may ask it on every keystroke and the refusal arrives BEFORE
|
|
6020
|
+
* the save rather than after it.
|
|
6021
|
+
*/
|
|
6022
|
+
checklistRefusal(args: {
|
|
6023
|
+
spec: ChecklistSpec;
|
|
6024
|
+
}): Promise<RecordsResult<string | null>>;
|
|
6025
|
+
/**
|
|
6026
|
+
* Store a checklist, whole: ordered steps, who each belongs to by role, how
|
|
6027
|
+
* many days in each is due, what each waits for, what each asks for, and what
|
|
6028
|
+
* starts a run. Pass `template_id` to change the checklist that already
|
|
6029
|
+
* exists rather than making a second one.
|
|
6030
|
+
*/
|
|
6031
|
+
checklistDeclare(args: {
|
|
6032
|
+
spec: ChecklistSpec;
|
|
6033
|
+
template_id?: Uuid | null;
|
|
6034
|
+
}): Promise<RecordsResult<ChecklistDeclared>>;
|
|
6035
|
+
checklistTemplates(args?: {
|
|
6036
|
+
about_table_id?: Uuid | null;
|
|
6037
|
+
limit?: number;
|
|
6038
|
+
}): Promise<RecordsResult<ChecklistTemplateSummary[]>>;
|
|
6039
|
+
checklistTemplateShape(args: {
|
|
6040
|
+
template_id: Uuid;
|
|
6041
|
+
}): Promise<RecordsResult<ChecklistTemplateShape>>;
|
|
6042
|
+
/**
|
|
6043
|
+
* Run a checklist for one record: one work item per step in the ONE work
|
|
6044
|
+
* layer, assigned by role to real people, dated from the offsets,
|
|
6045
|
+
* dependencies carried across. `roles` names who stands in each role for THIS
|
|
6046
|
+
* run, over whatever the checklist says by default.
|
|
6047
|
+
*/
|
|
6048
|
+
checklistStart(args: {
|
|
6049
|
+
template_id: Uuid;
|
|
6050
|
+
about_record_id?: Uuid | null;
|
|
6051
|
+
roles?: Record<string, Uuid>;
|
|
6052
|
+
startingAt?: Timestamp | null;
|
|
6053
|
+
}): Promise<RecordsResult<ChecklistRunStarted>>;
|
|
6054
|
+
checklistRun(args: {
|
|
6055
|
+
run_id: Uuid;
|
|
6056
|
+
}): Promise<RecordsResult<ChecklistRunStep[]>>;
|
|
6057
|
+
checklistRuns(args?: {
|
|
6058
|
+
about_table_id?: Uuid | null;
|
|
6059
|
+
about_record_id?: Uuid | null;
|
|
6060
|
+
includeClosed?: boolean;
|
|
6061
|
+
limit?: number;
|
|
6062
|
+
}): Promise<RecordsResult<ChecklistRunSummary[]>>;
|
|
6063
|
+
/**
|
|
6064
|
+
* Tick a step off with whatever it asked for. Refused by name while a step it
|
|
6065
|
+
* waits for is open, or while what it asks for is missing — and the same
|
|
6066
|
+
* refusal meets `workSetState`, because the rule lives in the store and not
|
|
6067
|
+
* in this door.
|
|
6068
|
+
*/
|
|
6069
|
+
checklistStepComplete(args: {
|
|
6070
|
+
step_id: Uuid;
|
|
6071
|
+
evidence?: Record<string, unknown>;
|
|
6072
|
+
}): Promise<RecordsResult<ChecklistStepCompleted>>;
|
|
6073
|
+
/** Why this step cannot be finished right now. `null` means it can. */
|
|
6074
|
+
checklistStepRefusal(args: {
|
|
6075
|
+
step_id: Uuid;
|
|
6076
|
+
}): Promise<RecordsResult<string | null>>;
|
|
6077
|
+
/** The five states and what each one may become. Asked, never hardcoded in a picker. */
|
|
6078
|
+
workStates(): Promise<RecordsResult<WorkState[]>>;
|
|
6079
|
+
/** Why this graph would be refused — asked BEFORE it is written. `null` means it is fine. */
|
|
6080
|
+
workTemplateRefusal(args: {
|
|
6081
|
+
graph: WorkGraph;
|
|
6082
|
+
}): Promise<RecordsResult<string | null>>;
|
|
6083
|
+
workTemplateDeclare(args: {
|
|
6084
|
+
name: string;
|
|
6085
|
+
graph: WorkGraph;
|
|
6086
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
6087
|
+
/**
|
|
6088
|
+
* REC-70: the WHOLE graph is created in one act, judged before any of it is
|
|
6089
|
+
* written, so a half-made checklist is not a state this store can be in.
|
|
6090
|
+
*/
|
|
6091
|
+
workTemplateInstantiate(args: {
|
|
6092
|
+
template_id: Uuid;
|
|
6093
|
+
overrides?: Record<string, Record<string, unknown>>;
|
|
6094
|
+
}): Promise<RecordsResult<WorkInstantiation>>;
|
|
6095
|
+
workTemplateShape(args: {
|
|
6096
|
+
template_id: Uuid;
|
|
6097
|
+
}): Promise<RecordsResult<unknown>>;
|
|
6098
|
+
workInstantiationShape(args: {
|
|
6099
|
+
instantiation_id: Uuid;
|
|
6100
|
+
}): Promise<RecordsResult<unknown>>;
|
|
6101
|
+
/** Whose turn each record is, with its state and whether that state is terminal. */
|
|
6102
|
+
workWhoseTurn(args: {
|
|
6103
|
+
table_id: Uuid;
|
|
6104
|
+
includeFinished?: boolean;
|
|
6105
|
+
}): Promise<RecordsResult<WorkTurn[]>>;
|
|
6106
|
+
/** Does this Table carry assignment at all? A screen asks before it offers one. */
|
|
6107
|
+
workHasAssignment(args: {
|
|
6108
|
+
table_id: Uuid;
|
|
6109
|
+
}): Promise<RecordsResult<boolean>>;
|
|
6110
|
+
/** The Fields assignment is made of, so nothing here invents a column name. */
|
|
6111
|
+
workAssignmentFields(args?: {
|
|
6112
|
+
options_table_id?: Uuid | null;
|
|
6113
|
+
}): Promise<RecordsResult<WorkAssignmentField[]>>;
|
|
6114
|
+
/** Add assignment to a Table. */
|
|
6115
|
+
workTakeAssignment(args: {
|
|
6116
|
+
table_id: Uuid;
|
|
6117
|
+
}): Promise<RecordsResult<unknown>>;
|
|
6118
|
+
/** Why this move would be refused. `null` means it is allowed. */
|
|
6119
|
+
workTransitionRefusal(args: {
|
|
6120
|
+
from_state_id: Uuid;
|
|
6121
|
+
to_state_id: Uuid;
|
|
6122
|
+
}): Promise<RecordsResult<string | null>>;
|
|
6123
|
+
/** Declare the Table slots are held in. Idempotent — a second call finds the first. */
|
|
6124
|
+
workSlotsDeclare(args: {
|
|
6125
|
+
name: string;
|
|
6126
|
+
slug: string;
|
|
6127
|
+
homeId?: Uuid | null;
|
|
6128
|
+
}): Promise<RecordsResult<unknown>>;
|
|
6129
|
+
/**
|
|
6130
|
+
* SCR-29. Take a slot for a while. THE STORE decides, under a unique index —
|
|
6131
|
+
* two people racing for the same slot do not both get it, whatever either
|
|
6132
|
+
* screen believed a moment earlier.
|
|
6133
|
+
*/
|
|
6134
|
+
workSlotHold(args: {
|
|
6135
|
+
table_id: Uuid;
|
|
6136
|
+
slotKey: string;
|
|
6137
|
+
holder: string;
|
|
6138
|
+
ttl?: string;
|
|
6139
|
+
}): Promise<RecordsResult<unknown>>;
|
|
6140
|
+
workSlotRelease(args: {
|
|
6141
|
+
hold_id: Uuid;
|
|
6142
|
+
}): Promise<RecordsResult<boolean>>;
|
|
6143
|
+
/** Every hold on this Table, with whether it has already lapsed. */
|
|
6144
|
+
workSlotHolds(args: {
|
|
6145
|
+
table_id: Uuid;
|
|
6146
|
+
}): Promise<RecordsResult<WorkSlotHold[]>>;
|
|
6147
|
+
workSlotExpire(args: {
|
|
6148
|
+
table_id: Uuid;
|
|
6149
|
+
}): Promise<RecordsResult<number>>;
|
|
6150
|
+
/**
|
|
6151
|
+
* THE ONE INBOX. Assignments, approvals and the agent's proposals, in one
|
|
6152
|
+
* ordered list with ONE row shape — PRODUCTS.md row 6. A second queue for the
|
|
6153
|
+
* agent's suggestions is the thing this replaces.
|
|
6154
|
+
*/
|
|
6155
|
+
workInbox(args?: {
|
|
6156
|
+
limit?: number;
|
|
6157
|
+
offset?: number;
|
|
6158
|
+
includeDecided?: boolean;
|
|
6159
|
+
/** Lane S5-PRIME-2: "inbox" (default), "snoozed" or "done" — this person's own views. */
|
|
6160
|
+
view?: WorkInboxView;
|
|
6161
|
+
}): Promise<RecordsResult<WorkInboxItem[]>>;
|
|
6162
|
+
/**
|
|
6163
|
+
* SNOOZE ONE ITEM OF MY INBOX UNTIL A TIME (lane S5-PRIME-2, `custom.inbox_snooze`). Only my
|
|
6164
|
+
* inbox changes; the approval or record is never written. A time already past, a snooze past a
|
|
6165
|
+
* year, and a decided item are refused by name.
|
|
6166
|
+
*/
|
|
6167
|
+
inboxSnooze(args: {
|
|
6168
|
+
item_id: Uuid;
|
|
6169
|
+
until: Timestamp;
|
|
6170
|
+
}): Promise<RecordsResult<InboxStateChange>>;
|
|
6171
|
+
/** Take my snooze off: it is back in my inbox now. */
|
|
6172
|
+
inboxUnsnooze(args: {
|
|
6173
|
+
item_id: Uuid;
|
|
6174
|
+
}): Promise<RecordsResult<InboxStateChange>>;
|
|
6175
|
+
/**
|
|
6176
|
+
* CLEAR (mark done) ONE ITEM OF MY INBOX. A decision still owed is refused ("This one needs a
|
|
6177
|
+
* decision"). It comes back if somebody else changes it.
|
|
6178
|
+
*/
|
|
6179
|
+
inboxClear(args: {
|
|
6180
|
+
item_id: Uuid;
|
|
6181
|
+
}): Promise<RecordsResult<InboxStateChange>>;
|
|
6182
|
+
/** Put a cleared item back in my inbox. */
|
|
6183
|
+
inboxUnclear(args: {
|
|
6184
|
+
item_id: Uuid;
|
|
6185
|
+
}): Promise<RecordsResult<InboxStateChange>>;
|
|
6186
|
+
/**
|
|
6187
|
+
* WHAT WAITS ON ME, COUNTED (`custom.inbox_counts`) — the same predicate the inbox lists with.
|
|
6188
|
+
* `everyOrganization` counts every organization I belong to (the shell badge: what waits on a
|
|
6189
|
+
* person is theirs, not the selected organization's).
|
|
6190
|
+
*/
|
|
6191
|
+
inboxCounts(args?: {
|
|
6192
|
+
everyOrganization?: boolean;
|
|
6193
|
+
}): Promise<RecordsResult<InboxCounts[]>>;
|
|
6194
|
+
/** "My work", "work I assigned", "waiting on somebody being chosen". */
|
|
6195
|
+
workList(args?: {
|
|
6196
|
+
flavour?: WorkListFlavour;
|
|
6197
|
+
includeFinished?: boolean;
|
|
6198
|
+
limit?: number;
|
|
6199
|
+
offset?: number;
|
|
6200
|
+
}): Promise<RecordsResult<WorkListItem[]>>;
|
|
6201
|
+
/**
|
|
6202
|
+
* Give one record to one person: the Assignee value AND editor access, in one
|
|
6203
|
+
* transaction. Passing no `user_id` un-assigns and says plainly that nobody's
|
|
6204
|
+
* access was taken away.
|
|
6205
|
+
*/
|
|
6206
|
+
workAssign(args: {
|
|
6207
|
+
record_id: Uuid;
|
|
6208
|
+
user_id?: Uuid | null;
|
|
6209
|
+
dueDate?: string | null;
|
|
6210
|
+
clearDue?: boolean;
|
|
6211
|
+
}): Promise<RecordsResult<WorkAssignment>>;
|
|
6212
|
+
/** The states this record may be moved to, and the sentence for each it may not. */
|
|
6213
|
+
workRecordStates(args: {
|
|
6214
|
+
record_id: Uuid;
|
|
6215
|
+
}): Promise<RecordsResult<WorkRecordState[]>>;
|
|
6216
|
+
/** Move it. The store refuses a move the model forbids, in its own words. */
|
|
6217
|
+
workSetState(args: {
|
|
6218
|
+
record_id: Uuid;
|
|
6219
|
+
state_id: Uuid | null;
|
|
6220
|
+
}): Promise<RecordsResult<unknown>>;
|
|
6221
|
+
/** The person-kernel record standing for a signed-in person here. */
|
|
6222
|
+
workPerson(args: {
|
|
6223
|
+
user_id: Uuid;
|
|
6224
|
+
create?: boolean;
|
|
6225
|
+
}): Promise<RecordsResult<Uuid | null>>;
|
|
6226
|
+
/** The templates this person may run, so a picker has ids to offer. */
|
|
6227
|
+
workTemplates(args?: {
|
|
6228
|
+
limit?: number;
|
|
6229
|
+
}): Promise<RecordsResult<Array<{
|
|
6230
|
+
template_id: Uuid;
|
|
6231
|
+
name: string;
|
|
6232
|
+
nodes: number;
|
|
6233
|
+
relations: number;
|
|
6234
|
+
created_at: string;
|
|
6235
|
+
}>>>;
|
|
6236
|
+
/** Who may decide a change about this subject, and why each of them may. */
|
|
6237
|
+
workApprovalApprovers(args: {
|
|
6238
|
+
subject_id: Uuid | null;
|
|
6239
|
+
approver_id?: Uuid | null;
|
|
6240
|
+
}): Promise<RecordsResult<WorkApprover[]>>;
|
|
6241
|
+
/** Ask for a change instead of making it. Viewer on the subject is enough to ASK. */
|
|
6242
|
+
workApprovalRequest(args: {
|
|
6243
|
+
subject_id: Uuid;
|
|
6244
|
+
change: WorkChange;
|
|
6245
|
+
note?: string | null;
|
|
6246
|
+
approver_id?: Uuid | null;
|
|
6247
|
+
origin?: "person" | "agent";
|
|
6248
|
+
conversation_id?: Uuid | null;
|
|
6249
|
+
}): Promise<RecordsResult<WorkApprovalFiled>>;
|
|
6250
|
+
/** Whether THIS person may decide THIS one — so a screen never draws a dead button. */
|
|
6251
|
+
workApprovalMayDecide(args: {
|
|
6252
|
+
approval_id: Uuid;
|
|
6253
|
+
}): Promise<RecordsResult<boolean>>;
|
|
6254
|
+
/** Approve or decline. Approving APPLIES the change, as the person approving. */
|
|
6255
|
+
workApprovalDecide(args: {
|
|
6256
|
+
approval_id: Uuid;
|
|
6257
|
+
approve: boolean;
|
|
6258
|
+
note?: string | null;
|
|
6259
|
+
}): Promise<RecordsResult<WorkApprovalDecision>>;
|
|
6260
|
+
/**
|
|
6261
|
+
* DECIDE MANY INBOX ITEMS IN ONE CALL (lane S4, `custom.work_decide_many`). Each is judged by
|
|
6262
|
+
* `work_approval_decide` exactly as one is, in its own savepoint: a refused decision leaves that
|
|
6263
|
+
* item waiting and the others still stand. Verdicts: approved, declined, already_decided,
|
|
6264
|
+
* no_right, refused — each with the store's own sentence.
|
|
6265
|
+
*/
|
|
6266
|
+
workDecideMany(args: {
|
|
6267
|
+
decisions: WorkDecideManyItem[];
|
|
6268
|
+
}): Promise<RecordsResult<WorkDecideMany>>;
|
|
6269
|
+
/** One waiting change in full, for the person deciding it or the one who asked. */
|
|
6270
|
+
workApprovalRead(args: {
|
|
6271
|
+
approval_id: Uuid;
|
|
6272
|
+
}): Promise<RecordsResult<Record<string, unknown>>>;
|
|
6273
|
+
/** VIS-31. Is this account a signed-in outsider — no NON-personal organization? */
|
|
6274
|
+
isExternalPrincipal(args?: {
|
|
6275
|
+
user_id?: Uuid | null;
|
|
6276
|
+
}): Promise<RecordsResult<boolean>>;
|
|
6277
|
+
/** The same answer WITH the plain-English reason a screen shows. */
|
|
6278
|
+
externalPrincipalCard(args?: {
|
|
6279
|
+
user_id?: Uuid | null;
|
|
6280
|
+
}): Promise<RecordsResult<ExternalPrincipalCard>>;
|
|
6281
|
+
/** Exactly the resource ids Visibility gave that outsider. Never an organization's list. */
|
|
6282
|
+
externalPrincipalReach(args: {
|
|
6283
|
+
resourceType: string;
|
|
6284
|
+
user_id?: Uuid | null;
|
|
6285
|
+
}): Promise<RecordsResult<Array<{
|
|
6286
|
+
resource_id: Uuid;
|
|
6287
|
+
}>>>;
|
|
6288
|
+
/** VIS-32. Bind a record or a view to a public address with a declared render mode. */
|
|
6289
|
+
publishBindingCreate(args: {
|
|
6290
|
+
slug: string;
|
|
6291
|
+
resourceType: string;
|
|
6292
|
+
resource_id: Uuid;
|
|
6293
|
+
renderMode?: string;
|
|
6294
|
+
}): Promise<RecordsResult<PublishBinding>>;
|
|
6295
|
+
publishBindingRevoke(args: {
|
|
6296
|
+
slug: string;
|
|
6297
|
+
}): Promise<RecordsResult<unknown>>;
|
|
6298
|
+
/** What a SIGNED-OUT visitor resolves. Empty for an invented, revoked or unpublished address. */
|
|
6299
|
+
resolvePublishBinding(args: {
|
|
6300
|
+
slug: string;
|
|
6301
|
+
}): Promise<RecordsResult<ResolvedPublishBinding[]>>;
|
|
6302
|
+
/** The same resolution plus what the address holds (table | record | dashboard | page | view). */
|
|
6303
|
+
resolvePublishBindingKind(args: {
|
|
6304
|
+
slug: string;
|
|
6305
|
+
}): Promise<RecordsResult<ResolvedPublishBindingKind[]>>;
|
|
6306
|
+
/** D-15. The ONE sentence admitting nothing was scanned, so four surfaces cannot drift. */
|
|
6307
|
+
worldPublishGapNotice(): Promise<RecordsResult<string>>;
|
|
6308
|
+
/** Put a resource in the world lane. Refuses by name while the lane is closed. */
|
|
6309
|
+
publishToWorld(args: {
|
|
6310
|
+
resourceType: string;
|
|
6311
|
+
resource_id: Uuid;
|
|
6312
|
+
discoverable?: boolean;
|
|
6313
|
+
}): Promise<RecordsResult<unknown>>;
|
|
6314
|
+
/**
|
|
6315
|
+
* Declare a Rule. It is NOT `recordWrite` into the rule kernel, and that is
|
|
6316
|
+
* the whole point: `custom.record_write` inserts `data_class = 'record'`, so a
|
|
6317
|
+
* document written that way is not a Rule and the store's own rule doors
|
|
6318
|
+
* (`custom.rule_members`, `custom.agg_subscriptions`) never see it. Writing
|
|
6319
|
+
* one through the record door and calling it a Rule would be a silent
|
|
6320
|
+
* failure — a screen that looked like it had subscribed you to something.
|
|
6321
|
+
*/
|
|
6322
|
+
ruleDeclare(args: {
|
|
6323
|
+
spec: Record<string, unknown>;
|
|
6324
|
+
rule_id?: Uuid | null;
|
|
6325
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
6326
|
+
fieldPropose(proposal: FieldProposal): Promise<RecordsResult<never>>;
|
|
6327
|
+
tablePropose(proposal: TableProposal): Promise<RecordsResult<never>>;
|
|
6328
|
+
promoteTable(args: {
|
|
6329
|
+
table_id: Uuid;
|
|
6330
|
+
}): Promise<RecordsResult<unknown>>;
|
|
6331
|
+
promoteField(args: {
|
|
6332
|
+
table_id: Uuid;
|
|
6333
|
+
field_id: Uuid;
|
|
6334
|
+
}): Promise<RecordsResult<unknown>>;
|
|
6335
|
+
/**
|
|
6336
|
+
* @deprecated The record store is never off (owner ruling, 2026-10-03: everything is on by
|
|
6337
|
+
* default). This answers `true` whenever the door answers; a refusal means the store could not
|
|
6338
|
+
* be reached, never that it is off. Do not gate a screen on it.
|
|
6339
|
+
*/
|
|
6340
|
+
storeIsOpen(): Promise<RecordsResult<boolean>>;
|
|
6341
|
+
/**
|
|
6342
|
+
* WHAT THIS PERSON MAY DO TO THESE THINGS — asked once, for a whole page.
|
|
6343
|
+
*
|
|
6344
|
+
* There is no principal argument, on purpose: the door resolves the caller
|
|
6345
|
+
* from the session, so a person can ask about their OWN access and about
|
|
6346
|
+
* nobody else's. A subject they hold nothing on answers `level: null`, which
|
|
6347
|
+
* is an answer; the row is never omitted, because a screen that could not
|
|
6348
|
+
* tell "no access" from "not asked yet" would draw one of them as the other.
|
|
6349
|
+
*/
|
|
6350
|
+
myLevels(args: {
|
|
6351
|
+
ids: Uuid[];
|
|
6352
|
+
subject?: "record";
|
|
6353
|
+
}): Promise<RecordsResult<MyLevel[]>>;
|
|
6354
|
+
/** G1. Write ONE leaf of a Table's colors, or clear it with `null`. Editor on the Table. */
|
|
6355
|
+
tableDecorate(args: {
|
|
6356
|
+
table_id: Uuid;
|
|
6357
|
+
path: DecorationPath;
|
|
6358
|
+
value: unknown;
|
|
6359
|
+
}): Promise<RecordsResult<TableDecorations>>;
|
|
6360
|
+
/** G1. A Table's colors as a screen paints them, with what went stale named. */
|
|
6361
|
+
tableDecorations(args: {
|
|
6362
|
+
table_id: Uuid;
|
|
6363
|
+
}): Promise<RecordsResult<TableDecorations>>;
|
|
6364
|
+
/** G1. The layout a grid opens with: platform → organization knob → the view's own. */
|
|
6365
|
+
gridLayout(args: {
|
|
6366
|
+
table_id: Uuid;
|
|
6367
|
+
view_id?: Uuid | null;
|
|
6368
|
+
}): Promise<RecordsResult<GridLayout>>;
|
|
6369
|
+
/** G3. The older grid's formula text → the store's expression. Never refuses a typo: answers ok:false. */
|
|
6370
|
+
formulaParse(args: {
|
|
6371
|
+
table_id: Uuid;
|
|
6372
|
+
text: string;
|
|
6373
|
+
}): Promise<RecordsResult<FormulaParse>>;
|
|
6374
|
+
/**
|
|
6375
|
+
* NOTION-PROPS. The formula being typed, parsed AND worked out for one record of the table
|
|
6376
|
+
* (`custom.formula_preview`): the parse, plus `value` — what a saved formula column would show on
|
|
6377
|
+
* that record — or `error` when it parses and cannot be worked out there. Writes nothing.
|
|
6378
|
+
*/
|
|
6379
|
+
formulaPreview(args: {
|
|
6380
|
+
table_id: Uuid;
|
|
6381
|
+
record_id: Uuid | null;
|
|
6382
|
+
text: string;
|
|
6383
|
+
}): Promise<RecordsResult<FormulaPreview>>;
|
|
6384
|
+
/** G2. Declare a Table's row actions — the whole list. Editor on the Table. */
|
|
6385
|
+
actionDeclare(args: {
|
|
6386
|
+
table_id: Uuid;
|
|
6387
|
+
actions: RowAction[];
|
|
6388
|
+
}): Promise<RecordsResult<RowAction[]>>;
|
|
6389
|
+
/** G2. A Table's row actions, each saying whether it can run here. */
|
|
6390
|
+
rowActions(args: {
|
|
6391
|
+
table_id: Uuid;
|
|
6392
|
+
}): Promise<RecordsResult<{
|
|
6393
|
+
actions: RowAction[];
|
|
6394
|
+
stale: unknown[];
|
|
6395
|
+
}>>;
|
|
6396
|
+
/**
|
|
6397
|
+
* G2. Run one action on a selection, in ONE transaction. A refusal changed NOTHING; read
|
|
6398
|
+
* every record and field that refused with `actionRefusals(result.error)`.
|
|
6399
|
+
*/
|
|
6400
|
+
actionRun(args: {
|
|
6401
|
+
action_id: Uuid;
|
|
6402
|
+
record_ids: Uuid[];
|
|
6403
|
+
}): Promise<RecordsResult<ActionRunResult>>;
|
|
6404
|
+
/**
|
|
6405
|
+
* AUTOMATION-DOOR. Declare (or, with `automation_id`, replace) one automation on a Table — editor on the Table.
|
|
6406
|
+
* A spec the store refuses comes back as `data.ok === false` with `_errors`, one sentence per path.
|
|
6407
|
+
*/
|
|
6408
|
+
automationDeclare(args: {
|
|
6409
|
+
table_id: Uuid;
|
|
6410
|
+
spec: AutomationSpec;
|
|
6411
|
+
automation_id?: Uuid | null;
|
|
6412
|
+
}): Promise<RecordsResult<AutomationDeclared>>;
|
|
6413
|
+
/** AUTOMATION-DOOR. A Table's automations with their last run; archived ones only when asked. */
|
|
6414
|
+
automations(args: {
|
|
6415
|
+
table_id: Uuid;
|
|
6416
|
+
include_archived?: boolean;
|
|
6417
|
+
}): Promise<RecordsResult<AutomationList>>;
|
|
6418
|
+
/** AUTOMATION-DOOR. Archive one (it switches off and keeps its history). Editor on the Table. */
|
|
6419
|
+
automationArchive(args: {
|
|
6420
|
+
automation_id: Uuid;
|
|
6421
|
+
}): Promise<RecordsResult<AutomationFlipped>>;
|
|
6422
|
+
/** AUTOMATION-DOOR. Bring an archived one back (it stays off until `automationSetEnabled`). */
|
|
6423
|
+
automationRestore(args: {
|
|
6424
|
+
automation_id: Uuid;
|
|
6425
|
+
}): Promise<RecordsResult<AutomationFlipped>>;
|
|
6426
|
+
/** AUTOMATION-DOOR. Switch one on or off. */
|
|
6427
|
+
automationSetEnabled(args: {
|
|
6428
|
+
automation_id: Uuid;
|
|
6429
|
+
enabled: boolean;
|
|
6430
|
+
}): Promise<RecordsResult<AutomationFlipped>>;
|
|
6431
|
+
/** AUTOMATION-DOOR. Run history, newest first: status, the store's own sentence, every step. */
|
|
6432
|
+
automationRuns(args: {
|
|
6433
|
+
automation_id: Uuid;
|
|
6434
|
+
limit?: number;
|
|
6435
|
+
cursor?: string | null;
|
|
6436
|
+
}): Promise<RecordsResult<AutomationRuns>>;
|
|
6437
|
+
/** G4. Send every change to this Table's records to an https webhook. Admin. The secret is shown once. */
|
|
6438
|
+
tableWebhookDeclare(args: {
|
|
6439
|
+
table_id: Uuid;
|
|
6440
|
+
target_url: string;
|
|
6441
|
+
events?: RecordEvent[] | null;
|
|
6442
|
+
description?: string | null;
|
|
6443
|
+
}): Promise<RecordsResult<TableWebhookDeclared>>;
|
|
6444
|
+
/** G4. The webhooks a Table sends to, with their delivery health — never the secret. */
|
|
6445
|
+
tableWebhooks(args: {
|
|
6446
|
+
table_id: Uuid;
|
|
6447
|
+
}): Promise<RecordsResult<TableWebhook[]>>;
|
|
6448
|
+
/** G4. Switch one off. It is never deleted. */
|
|
6449
|
+
tableWebhookArchive(args: {
|
|
6450
|
+
webhook_id: Uuid;
|
|
6451
|
+
}): Promise<RecordsResult<boolean>>;
|
|
6452
|
+
/** G5. Number the records an autonumber column found already there, in creation order. */
|
|
6453
|
+
autonumberBackfill(args: {
|
|
6454
|
+
field_id: Uuid;
|
|
6455
|
+
}): Promise<RecordsResult<{
|
|
6456
|
+
numbered: number;
|
|
6457
|
+
highest: number | null;
|
|
6458
|
+
says: string;
|
|
6459
|
+
}>>;
|
|
6460
|
+
/**
|
|
6461
|
+
* NOTION-PROPS-3. PRESS A BUTTON COLUMN ON ONE ROW (`custom.button_press`): a link comes back filled from
|
|
6462
|
+
* the row for the screen to open; a row action or an automation runs in the store and its result comes
|
|
6463
|
+
* back. A button with nothing set up is refused by name (22023).
|
|
6464
|
+
*/
|
|
6465
|
+
buttonPress(args: {
|
|
6466
|
+
record_id: Uuid;
|
|
6467
|
+
field_id: Uuid;
|
|
6468
|
+
}): Promise<RecordsResult<ButtonPressed>>;
|
|
6469
|
+
/**
|
|
6470
|
+
* NOTION-PROPS-3. The knob `data/timeline_dependency_shift` for the signed-in person in this organization:
|
|
6471
|
+
* whether moving a record on a timeline moves the records waiting on it (default true).
|
|
6472
|
+
*/
|
|
6473
|
+
timelineDependencyShift(): Promise<RecordsResult<boolean>>;
|
|
6474
|
+
/** G5. One page of the export door — exactly the rows and columns the read door serves this person. */
|
|
6475
|
+
ioExport(args: {
|
|
6476
|
+
table_id: Uuid;
|
|
6477
|
+
columns?: string[] | null;
|
|
6478
|
+
limit?: number;
|
|
6479
|
+
}): Promise<RecordsResult<IoExportPage>>;
|
|
6480
|
+
/** G5. That page as an .xlsx; a withheld column is named on its own sheet. */
|
|
6481
|
+
/**
|
|
6482
|
+
* G9. Every table a picker may offer here, from BOTH stores, each saying which store opens it.
|
|
6483
|
+
* A table the app keeps out of default lists (`custom.table_kept_out_of_lists`: an agent's
|
|
6484
|
+
* outputs) is left out unless `include_platform_tables` is true — the "Show platform tables" switch.
|
|
6485
|
+
*/
|
|
6486
|
+
tableListEverywhere(args?: {
|
|
6487
|
+
include_platform_tables?: boolean;
|
|
6488
|
+
}): Promise<RecordsResult<{
|
|
6489
|
+
success: boolean;
|
|
6490
|
+
tables: TableListEntry[];
|
|
6491
|
+
}>>;
|
|
6492
|
+
/**
|
|
6493
|
+
* Every table the person reaches (`custom.data_home_tables`), as the data home lists them.
|
|
6494
|
+
* `organization_id` names one organization; `null` asks for every organization the person
|
|
6495
|
+
* reaches — never the client's bound organization by default. A table the app keeps out of
|
|
6496
|
+
* default lists (an agent's outputs) is answered only with `include_platform_tables: true`.
|
|
6497
|
+
*/
|
|
6498
|
+
dataHomeTables(args: {
|
|
6499
|
+
organization_id: Uuid | null;
|
|
6500
|
+
include_platform_tables?: boolean;
|
|
6501
|
+
}): Promise<RecordsResult<DataHomeTable[]>>;
|
|
6502
|
+
/**
|
|
6503
|
+
* Every table of EVERY organization (`custom.admin_all_tables`) — the admin section's list. The
|
|
6504
|
+
* store's walls admit a platform admin to system organizations only, so this is a separate door that
|
|
6505
|
+
* answers only on the admin lane for a platform admin; anyone else gets a refusal, not an empty list.
|
|
6506
|
+
*/
|
|
6507
|
+
adminAllTables(): Promise<RecordsResult<AdminTable[]>>;
|
|
6508
|
+
/**
|
|
6509
|
+
* G10. Refresh a synced source (a sheet tab) into ONE Table under `home_id`: new rows added,
|
|
6510
|
+
* changed rows updated, rows the source dropped archived — never destroyed; columns the
|
|
6511
|
+
* person added in Matrx survive. Build the spec with `sheetSyncSpec`.
|
|
6512
|
+
*/
|
|
6513
|
+
tableSync(args: {
|
|
6514
|
+
home_id: Uuid;
|
|
6515
|
+
spec: TableSyncSpec;
|
|
6516
|
+
}): Promise<RecordsResult<TableSyncResult>>;
|
|
6517
|
+
/**
|
|
6518
|
+
* G11. The record-store Table a context scope's template-bound item provisions — one per item
|
|
6519
|
+
* and scope. A scope provisioned before the move answers with its moved Table (same id); the
|
|
6520
|
+
* Home defaults to the organization's own.
|
|
6521
|
+
*/
|
|
6522
|
+
scopeTableProvision(args: {
|
|
6523
|
+
item_id: Uuid;
|
|
6524
|
+
scope_id: Uuid;
|
|
6525
|
+
home_id?: Uuid | null;
|
|
6526
|
+
}): Promise<RecordsResult<Uuid>>;
|
|
6527
|
+
/** G12. The rows of each Table this reader may see, in one call (fold with `withRowCounts`). A Table she may not know gets no row. */
|
|
6528
|
+
tableRowCounts(args: {
|
|
6529
|
+
table_ids: Uuid[];
|
|
6530
|
+
}): Promise<RecordsResult<TableRowCount[]>>;
|
|
6531
|
+
/** G12. Each live record's own header (created, updated, version) that the read door does not answer. */
|
|
6532
|
+
recordHeaders(args: {
|
|
6533
|
+
ids: Uuid[];
|
|
6534
|
+
}): Promise<RecordsResult<RecordHeader[]>>;
|
|
6535
|
+
/**
|
|
6536
|
+
* G14. Share a Table with a person by email or account id: an existing account outside the
|
|
6537
|
+
* organization is granted at once and notified (never made a member); an address with no
|
|
6538
|
+
* account is invited. The organization's outside-sharing setting decides first.
|
|
6539
|
+
*/
|
|
6540
|
+
tableShareOutsideGrant(args: {
|
|
6541
|
+
table_id: Uuid;
|
|
6542
|
+
person: string;
|
|
6543
|
+
level?: "viewer" | "commenter" | "editor" | "admin";
|
|
6544
|
+
}): Promise<RecordsResult<OutsideShareAnswer>>;
|
|
6545
|
+
/** G13. Keep a hand-set order on a saved view: the named rows first, in this order (build it with `moveInOrder`). */
|
|
6546
|
+
viewRecordOrderSet(args: {
|
|
6547
|
+
view_id: Uuid;
|
|
6548
|
+
record_ids: Uuid[];
|
|
6549
|
+
}): Promise<RecordsResult<ViewOrderSet>>;
|
|
6550
|
+
/**
|
|
6551
|
+
* G13 + ORDER-FILTER. A page of a hand-ordered view: placed rows by position, then the rest by
|
|
6552
|
+
* created time. `filter` is the list door's question (`StoreFilter`: a flat map or a nested
|
|
6553
|
+
* Rule — the view's own `where`, or a number clicked on a dashboard); given, the store reads
|
|
6554
|
+
* exactly the rows that match, in their places, and `limit`/`offset` page THAT order. Each row
|
|
6555
|
+
* answers the position stored for it; rows the filter hides keep theirs.
|
|
6556
|
+
*/
|
|
6557
|
+
readInViewOrder(args: {
|
|
6558
|
+
view_id: Uuid;
|
|
6559
|
+
filter?: StoreFilter | null | undefined;
|
|
6560
|
+
limit?: number;
|
|
6561
|
+
offset?: number;
|
|
6562
|
+
}): Promise<RecordsResult<Array<ReadRow & {
|
|
6563
|
+
position: number | null;
|
|
6564
|
+
}>>>;
|
|
6565
|
+
exportXlsx(args: {
|
|
6566
|
+
table_id: Uuid;
|
|
6567
|
+
columns?: string[] | null;
|
|
6568
|
+
limit?: number;
|
|
6569
|
+
labels?: Record<string, string>;
|
|
6570
|
+
sheetLabel?: string;
|
|
6571
|
+
}): Promise<RecordsResult<Uint8Array>>;
|
|
6572
|
+
}
|
|
6573
|
+
/** One Table's two lane facts, as `custom.table_facts` answers them. */
|
|
6574
|
+
interface TableFact {
|
|
6575
|
+
table_id: Uuid;
|
|
6576
|
+
/**
|
|
6577
|
+
* The old lane word (personal · internal · public), now worked out by the store from `shown_to`
|
|
6578
|
+
* and `published_to_web` (access ladder). Read those two; this stays for older stores.
|
|
6579
|
+
*/
|
|
6580
|
+
visibility: string;
|
|
6581
|
+
/** Whether the person signed in MADE this Table. Never who did. */
|
|
6582
|
+
mine: boolean;
|
|
6583
|
+
/** Access ladder "Shown to": only_me · my_team · everyone · everyone_on_ai_matrx; null = the default. */
|
|
6584
|
+
shown_to?: string | null;
|
|
6585
|
+
/** Access ladder "Published to the web": the only way anyone outside the organization opens it. */
|
|
6586
|
+
published_to_web?: boolean;
|
|
6587
|
+
}
|
|
6588
|
+
/**
|
|
6589
|
+
* WHERE A TABLE IS CURRENTLY READ AND WRITTEN during the older-table cutover.
|
|
6590
|
+
* `tableHome` is an address read from one Table record; this applies the
|
|
6591
|
+
* organization's migration switch to a batch of ids, including same-id copies.
|
|
6592
|
+
*/
|
|
6593
|
+
interface TableLiveLocation {
|
|
6594
|
+
table_id: Uuid;
|
|
6595
|
+
lives_in: "record" | "older";
|
|
6596
|
+
why: string | null;
|
|
6597
|
+
}
|
|
6598
|
+
/**
|
|
6599
|
+
* The facts folded onto a table list: `visibility` on every Table the facts name,
|
|
6600
|
+
* `created_by` ONLY as the caller's own id and only on the Tables the caller made.
|
|
6601
|
+
* Pure — returns new objects and leaves the list it was given alone.
|
|
6602
|
+
*/
|
|
6603
|
+
declare function withTableFacts<T extends {
|
|
6604
|
+
id: Uuid;
|
|
6605
|
+
}>(tables: readonly T[], facts: readonly TableFact[] | null | undefined, me: Uuid | null | undefined): T[];
|
|
6606
|
+
declare function createRecordsClient(given: RecordsConfig): RecordsClient;
|
|
6607
|
+
/**
|
|
6608
|
+
* Turn a refusal into the conflict a screen can SHOW: which version you wrote
|
|
6609
|
+
* against, which one won, and every field you touched as it stands now. Returns
|
|
6610
|
+
* null when the refusal was not a stale write.
|
|
6611
|
+
*/
|
|
6612
|
+
declare function asWriteConflict(error: RecordsError, recordId: Uuid): WriteConflict | null;
|
|
6613
|
+
|
|
6614
|
+
export { type ChecklistTemplateSummary as $, ARCHIVE_LANES as A, type AutomationTrigger as B, type AutomationValue as C, type AutomationValues as D, type AutomationWeekday as E, type FieldDrift as F, BUILT_KIND_WORD as G, CHOICE_NUDGES as H, type CaptureField as I, type CaptureFileRef as J, type CaptureOutcome as K, type CaptureQuestion as L, type CaptureSheetFace as M, type CaptureSheetSummary as N, type ChecklistDeclared as O, type ChecklistRequirement as P, type ChecklistRequirementKind as Q, type RecordsClient as R, type ChecklistRoleSpec as S, type TableArchiveProgress as T, type ChecklistRunStarted as U, type ChecklistRunStep as V, type ChecklistRunSummary as W, type ChecklistSpec as X, type ChecklistStepCompleted as Y, type ChecklistStepSpec as Z, type ChecklistTemplateShape as _, type TableKindFacts as a, type EntityFieldRights as a$, type ChecklistTrigger as a0, type ChecklistTriggerKind as a1, type ChoiceCellBack as a2, type ChoiceLike as a3, type ChoiceNudge as a4, type ChoiceOption as a5, type ChoiceRehome as a6, type ChoiceUsage as a7, type ChoicesRehomed as a8, type CommentThreadRead as a9, type DrillDeclaration as aA, type DrillDefinition as aB, type DrillDimension as aC, type DrillFinding as aD, type DrillGrain as aE, type DrillHaving as aF, type DrillLane as aG, type DrillLevel as aH, type DrillMeasure as aI, type DrillMeasureOp as aJ, type DrillMeasureWhereValue as aK, type DrillPath as aL, type DrillQuestion as aM, type DrillRecords as aN, type DrillRowsPage as aO, type DrillSource as aP, type DrillView as aQ, type EnrichAlternate as aR, type EnrichCell as aS, type EnrichDeclared as aT, type EnrichDueRow as aU, type EnrichRun as aV, type EnrichSource as aW, type Enrichment as aX, type EnrichmentSummary as aY, type EntityBackLinkItem as aZ, type EntityBackLinks as a_, type CommentWritten as aa, type ConversationScope as ab, type ConversationScopeContext as ac, type CustomFieldTableType as ad, DEFAULT_ARCHIVE_LANE as ae, DEFAULT_PAGE_SIZE as af, DRILL_CHART_TOKENS as ag, DRILL_DESCRIPTION_MAX as ah, DRILL_DOORS as ai, DRILL_SCHEMA as aj, type DataHomeTable as ak, type DecorationColor as al, type DecorationPath as am, type DecorationRule as an, type DecorationRuleOp as ao, type DecorationTarget as ap, type DocRenderRow as aq, type DocSignatureCheck as ar, type DocSignatureRow as as, type DocTemplateRow as at, type DocToken as au, type DocUnresolvedToken as av, type DrillAdHocOp as aw, type DrillAnswer as ax, type DrillAnswerRow as ay, type DrillChartToken as az, ARCHIVE_LANE_LABEL as b, ROW_WEB_NOT_READY as b$, type EntityFieldValue as b0, type EntityFieldsAcross as b1, type EntityRecordMatch as b2, type EntityRecordRead as b3, type EntityRecordsFound as b4, type EntityRowWritten as b5, type EntityTableFacts as b6, type ExternalPrincipalCard as b7, type FieldDriftAspect as b8, type FieldHistoryEntry as b9, type IoExportPage as bA, type MigrationEntry as bB, type MigrationUndone as bC, type NewEntityFieldDeclaration as bD, type OutsideShareAnswer as bE, PIPELINE_RULE_KINDS as bF, type ParentExtracted as bG, type Pipeline as bH, type PipelineColumn as bI, type PipelineDeclared as bJ, type PipelineGate as bK, type PipelineGatePreview as bL, type PipelineMissingField as bM, type PipelineMoveMany as bN, type PipelineMoveManyItem as bO, type PipelineMoveManyResult as bP, type PipelineMoveResult as bQ, type PipelineMoveVerdict as bR, type PipelineRule as bS, type PipelineRuleKind as bT, type PipelineSpec as bU, type PipelineStage as bV, type PipelineVerdict as bW, type PromotedPredicate as bX, type PublishBinding as bY, type PublishBindingKind as bZ, type QueryPlan as b_, type FieldRetyped as ba, type FormArchiveAnswer as bb, type FormulaParse as bc, type FormulaPreview as bd, type GridLayout as be, type GridLayoutMode as bf, type GridRowHeight as bg, type HistoryActor as bh, type HistoryActorKind as bi, type HistoryChange as bj, type Home as bk, type ImportBatchResult as bl, type ImportColumnPlan as bm, type ImportColumnsDeclared as bn, type ImportFinished as bo, type ImportOpened as bp, type ImportOutcome as bq, type ImportPlan as br, type ImportPolicy as bs, type ImportProposal as bt, type ImportReport as bu, type ImportRun as bv, type InboundAddress as bw, type InboundDeclared as bx, type InboxCounts as by, type InboxStateChange as bz, ARCHIVE_LANE_MEANS as c, type TableSyncSource as c$, type RecordChangeAction as c0, type RecordComment as c1, type RecordEvent as c2, type RecordHeader as c3, type RecordHistoryEntry as c4, type RecordQuery as c5, type RecordRowControls as c6, type RecordScopeComment as c7, type RecordScopeContext as c8, type RecordScopeField as c9, TABLE_KIND_PREFIX as cA, type Table as cB, type TableCapacity as cC, type TableCopyInProgress as cD, type TableDecorations as cE, type TableDuplicateProgress as cF, type TableDuplicated as cG, type TableFact as cH, type TableHome as cI, type TableHomeDestination as cJ, type TableLevel as cK, type TableLevelApproval as cL, type TableLevelFacts as cM, type TableLevelSet as cN, type TableListEntry as cO, type TableLiveLocation as cP, type TableMoved as cQ, type TablePlacement as cR, type TablePlacementFact as cS, type TableReaderRule as cT, type TableRenderSchema as cU, type TableRestoreProgress as cV, type TableRowCount as cW, type TableRowDefaults as cX, type TableRowDefaultsPatch as cY, type TableSchemaMode as cZ, type TableSyncResult as c_, type RecordScopeHistoryEntry as ca, type RecordScopeRelation as cb, type RecordScopeWithheld as cc, type RecordSplit as cd, type RecordsMerged as ce, type RegisteredTable as cf, type ResolvedPublishBinding as cg, type ResolvedPublishBindingKind as ch, type RestorePreview as ci, type RestoreResult as cj, type RetypeBehaviour as ck, type RetypePreview as cl, type RowAction as cm, type RowActionStep as cn, type RowDefaultsApplied as co, SHOWN_TO_LABEL as cp, SHOWN_TO_VALUES as cq, SHOWN_TO_WHO_MAY_CHANGE as cr, STAGE_RULE_ENFORCEMENT as cs, STAGE_RULE_ON_FAIL as ct, type ShownTo as cu, type StagePending as cv, type StagePendingOnBoard as cw, type StageRuleEnforcement as cx, type StageRuleOnFail as cy, type StageRuleWarning as cz, A_PERSONS_REFUSAL as d, moveConsequence as d$, type TableSyncSpec as d0, type TableWebhook as d1, type TableWebhookDeclared as d2, type TypedChoiceDecision as d3, type ViewLayout as d4, type ViewOrderSet as d5, type WorkApprovalDecision as d6, type WorkApprovalFiled as d7, type WorkApprovalState as d8, type WorkApprover as d9, asChoiceNudge as dA, asWriteConflict as dB, choiceSlug as dC, choiceValuesOf as dD, choicesOf as dE, createRecordsClient as dF, decideTypedChoice as dG, declareDrillDefinition as dH, drillAnswerOf as dI, drillFindingKnob as dJ, emptyArchiveLine as dK, exportPageXlsx as dL, fieldKindOf as dM, holdsARetiredChoice as dN, intersectIds as dO, isAPersonsRefusal as dP, isArchiveLane as dQ, isFoundation as dR, isShownTo as dS, isTableKind as dT, isTheChosen as dU, keptGroups as dV, keptOutOfSight as dW, keptTableHref as dX, levelHasShownTo as dY, looksLikeAnId as dZ, mayDrag as d_, type WorkAssignment as da, type WorkAssignmentField as db, type WorkChange as dc, type WorkDecideMany as dd, type WorkDecideManyItem as de, type WorkDecideManyResult as df, type WorkDecideVerdict as dg, type WorkDueState as dh, type WorkGraph as di, type WorkInboxItem as dj, type WorkInboxKind as dk, type WorkInboxView as dl, type WorkInstantiation as dm, type WorkListFlavour as dn, type WorkListItem as dp, type WorkOrigin as dq, type WorkRecordState as dr, type WorkSlotHold as ds, type WorkState as dt, type WorkTemplateNode as du, type WorkTemplateRelation as dv, type WorkTurn as dw, actionRefusals as dx, archivedByLine as dy, archivedWhen as dz, type ActionRefusal as e, moveInOrder as e0, offeredAsContext as e1, optionKey as e2, optionLabel as e3, parseFieldDrift as e4, parseTableCopiesInProgress as e5, parseTableDuplicateProgress as e6, parseTableDuplicated as e7, parseTableHome as e8, parseTableMoved as e9, planQuery as ea, previewRetype as eb, previewRuleChange as ec, recordChangeTrigger as ed, recordSourceKey as ee, recordSourceTable as ef, recordsUseSentence as eg, rehomeSentence as eh, removedChoicesInUse as ei, ruleThatRefuses as ej, rulesWithTopStar as ek, sameDocument as el, scopeChip as em, sheetSyncSpec as en, tableIdOf as eo, tableJsonSchema as ep, tableKindMapping as eq, tableKindSlug as er, tableRenderSchema as es, valueConverts as et, withRowCounts as eu, withTableFacts as ev, withTablePlacement as ew, type ActionRunResult as f, type AdminTable as g, type AnonTokenBinding as h, type ArchiveLane as i, type ArchivedChecklistTemplate as j, type ArchivedDoorRow as k, type ArchivedForm as l, type ArchivedRow as m, type AsOf as n, type AutomationAction as o, type AutomationDeclared as p, type AutomationFilter as q, type AutomationFlipped as r, type AutomationItem as s, type AutomationLastRun as t, type AutomationList as u, type AutomationRun as v, type AutomationRunStatus as w, type AutomationRuns as x, type AutomationSpec as y, type AutomationStep as z };
|