@ai-matrx/records 0.98.8 → 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.
Files changed (92) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/{table-kind-CboiMJuE.d.cts → client-9fzhCPD5.d.cts} +2771 -4
  3. package/dist/{table-kind-B4sdlvHf.d.ts → client-DcWZjmg2.d.ts} +2771 -4
  4. package/dist/core/index.cjs +100 -3
  5. package/dist/core/index.cjs.map +1 -1
  6. package/dist/core/index.d.cts +19 -17
  7. package/dist/core/index.d.ts +19 -17
  8. package/dist/core/index.js +100 -3
  9. package/dist/core/index.js.map +1 -1
  10. package/dist/data/index.cjs +52 -0
  11. package/dist/data/index.cjs.map +1 -1
  12. package/dist/data/index.d.cts +11 -12
  13. package/dist/data/index.d.ts +11 -12
  14. package/dist/data/index.js +52 -0
  15. package/dist/data/index.js.map +1 -1
  16. package/dist/{declareTable-BIuPJ3Vj.d.ts → declareTable-B6ic3leL.d.ts} +3 -4
  17. package/dist/{declareTable-d-HxRmF0.d.cts → declareTable-_GwN-ERY.d.cts} +3 -4
  18. package/dist/{doors-Bx3Shs3z.d.cts → doors-Dm5q9H8Y.d.cts} +1 -1
  19. package/dist/{doors-BTifsjNv.d.ts → doors-t-Oc2l9E.d.ts} +1 -1
  20. package/dist/entity/index.d.cts +7 -7
  21. package/dist/entity/index.d.ts +7 -7
  22. package/dist/{field-CJtssH3q.d.ts → field-BIRNApm1.d.ts} +2 -2
  23. package/dist/{field-DoVl2I9K.d.cts → field-BLy8drjM.d.cts} +2 -2
  24. package/dist/forms/index.d.cts +3 -3
  25. package/dist/forms/index.d.ts +3 -3
  26. package/dist/index.cjs +45 -0
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +30 -13
  29. package/dist/index.d.ts +30 -13
  30. package/dist/index.js +45 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/memory/index.d.cts +7 -7
  33. package/dist/memory/index.d.ts +7 -7
  34. package/dist/{objectOrganization-Crk9gJUM.d.ts → objectOrganization-D5Ytjah7.d.ts} +1 -1
  35. package/dist/{objectOrganization-CUa6jjhV.d.cts → objectOrganization-zgpoUAH1.d.cts} +1 -1
  36. package/dist/{port-CRP5g9l9.d.cts → port-B9glCG2h.d.cts} +3 -3
  37. package/dist/{port-CtnELAJQ.d.ts → port-C-p-_lAu.d.ts} +3 -3
  38. package/dist/{portal-DW5NGBT0.d.ts → portal-B9HCNPTc.d.ts} +2 -2
  39. package/dist/{portal-C4N9ByaY.d.cts → portal-C_LgvDeh.d.cts} +2 -2
  40. package/dist/{ports-WwHHNwge.d.ts → ports-BE_5jz-c.d.ts} +2 -2
  41. package/dist/{ports-YIh9jrCZ.d.cts → ports-BIdYUS-C.d.cts} +2 -2
  42. package/dist/questions/index.d.cts +9 -10
  43. package/dist/questions/index.d.ts +9 -10
  44. package/dist/react/index.cjs +97 -0
  45. package/dist/react/index.cjs.map +1 -1
  46. package/dist/react/index.d.cts +86 -1
  47. package/dist/react/index.d.ts +86 -1
  48. package/dist/react/index.js +97 -0
  49. package/dist/react/index.js.map +1 -1
  50. package/dist/realtime/index.d.cts +3 -3
  51. package/dist/realtime/index.d.ts +3 -3
  52. package/dist/{record-CxGK1OEK.d.cts → record-BrJNCmH1.d.cts} +1 -1
  53. package/dist/{record-CxGK1OEK.d.ts → record-BrJNCmH1.d.ts} +1 -1
  54. package/dist/{relation-Dh-lCkkh.d.ts → relation-BxGXLRaG.d.ts} +3 -3
  55. package/dist/{relation-DSGhM3tO.d.cts → relation-R10qQyQU.d.cts} +3 -3
  56. package/dist/{rule-DQpC7WqT.d.cts → rule-BGtYd6Pf.d.cts} +2 -2
  57. package/dist/{rule-xNwJF6Qo.d.ts → rule-BtjrE42J.d.ts} +2 -2
  58. package/dist/scopes/index.d.cts +3 -3
  59. package/dist/scopes/index.d.ts +3 -3
  60. package/dist/search/index.d.cts +1 -1
  61. package/dist/search/index.d.ts +1 -1
  62. package/dist/setup/index.cjs +52 -0
  63. package/dist/setup/index.cjs.map +1 -1
  64. package/dist/setup/index.d.cts +12 -13
  65. package/dist/setup/index.d.ts +12 -13
  66. package/dist/setup/index.js +52 -0
  67. package/dist/setup/index.js.map +1 -1
  68. package/dist/{subscription-BVCn1PVe.d.cts → subscription-BEM4B4dR.d.cts} +3 -3
  69. package/dist/{subscription-DQzPVKBR.d.ts → subscription-Ca15Z7Gu.d.ts} +3 -3
  70. package/dist/templates/index.d.cts +10 -10
  71. package/dist/templates/index.d.ts +10 -10
  72. package/dist/typed-table/index.cjs +52 -0
  73. package/dist/typed-table/index.cjs.map +1 -1
  74. package/dist/typed-table/index.d.cts +10 -11
  75. package/dist/typed-table/index.d.ts +10 -11
  76. package/dist/typed-table/index.js +52 -0
  77. package/dist/typed-table/index.js.map +1 -1
  78. package/dist/{types-3lM5f6b0.d.cts → types-5ql9_q-o.d.cts} +2 -2
  79. package/dist/{types-04kFNi3-.d.ts → types-BALEbMc8.d.ts} +2 -2
  80. package/dist/{types-DKJO83lQ.d.cts → types-BhnjvJ8U.d.cts} +2 -2
  81. package/dist/{types-SUAmeBId.d.ts → types-CURw95qc.d.ts} +2 -2
  82. package/dist/{types-DKeGkHpE.d.cts → types-DRMeL0uW.d.cts} +2 -2
  83. package/dist/{types-DJVccwh0.d.ts → types-_odOqLOe.d.ts} +2 -2
  84. package/dist/use-cases/index.d.cts +5 -5
  85. package/dist/use-cases/index.d.ts +5 -5
  86. package/dist/{validate-BIJtP2KB.d.cts → validate-Cdtk0y18.d.cts} +1 -1
  87. package/dist/{validate--y-pPc-c.d.ts → validate-ChibJPPI.d.ts} +1 -1
  88. package/dist/views/index.d.cts +9 -10
  89. package/dist/views/index.d.ts +9 -10
  90. package/package.json +3 -3
  91. package/dist/client-C1B-MNzb.d.ts +0 -2704
  92. package/dist/client-D2jAgJNn.d.cts +0 -2704
@@ -1,6 +1,11 @@
1
- import { U as Uuid, h as Timestamp, q as ReadRow, l as RecordDocument, T as TableType, b as TableDisplay, S as StorageMode, aw as TableOrigin, u as StoredRecord, y as ParityFieldType, a as RecordsError } from './record-CxGK1OEK.cjs';
2
- import { F as Field } from './field-DoVl2I9K.cjs';
3
- import { g as PermissionLevel } from './ports-YIh9jrCZ.cjs';
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
- export { type ImportRun as $, type ArchiveLane as A, type PipelineMoveResult as B, type ChoiceNudge as C, type PipelineMoveManyItem as D, type EntityTableFacts as E, type FieldDrift as F, type PipelineMoveMany as G, type PipelineSpec as H, type PipelineDeclared as I, type StageRuleEnforcement as J, type StagePending as K, type StagePendingOnBoard as L, type MigrationUndone as M, type NewEntityFieldDeclaration as N, type PipelineGate as O, type Pipeline as P, type PipelineGatePreview as Q, type RecordsMerged as R, type StageRuleOnFail as S, type TableArchiveProgress as T, type ImportPlan as U, type ImportPolicy as V, type ImportOpened as W, type ImportColumnsDeclared as X, type ImportBatchResult as Y, type ImportFinished as Z, type ImportReport as _, type TableRestoreProgress as a, type WorkApprovalDecision as a$, type InboundDeclared as a0, type InboundAddress as a1, type FormArchiveAnswer as a2, type ArchivedForm as a3, type ArchivedChecklistTemplate as a4, type TableRowDefaults as a5, type TableRowDefaultsPatch as a6, type RowDefaultsApplied as a7, type RecordRowControls as a8, type CaptureSheetSummary as a9, type CommentWritten as aA, type AnonTokenBinding as aB, type ChecklistSpec as aC, type ChecklistDeclared as aD, type ChecklistTemplateSummary as aE, type ChecklistTemplateShape as aF, type ChecklistRunStarted as aG, type ChecklistRunStep as aH, type ChecklistRunSummary as aI, type ChecklistStepCompleted as aJ, type WorkState as aK, type WorkGraph as aL, type WorkInstantiation as aM, type WorkTurn as aN, type WorkAssignmentField as aO, type WorkSlotHold as aP, type WorkInboxView as aQ, type WorkInboxItem as aR, type InboxStateChange as aS, type InboxCounts as aT, type WorkListFlavour as aU, type WorkListItem as aV, type WorkAssignment as aW, type WorkRecordState as aX, type WorkApprover as aY, type WorkChange as aZ, type WorkApprovalFiled as a_, type CaptureSheetFace as aa, type CaptureFileRef as ab, type CaptureOutcome as ac, type EnrichmentSummary as ad, type EnrichDeclared as ae, type EnrichDueRow as af, type EnrichCell as ag, type EnrichRun as ah, type DrillSource as ai, type DrillDefinition as aj, type DrillQuestion as ak, type DrillAnswer as al, type DrillRowsPage as am, type DocToken as an, type DocUnresolvedToken as ao, type DocTemplateRow as ap, type DocRenderRow as aq, type DocSignatureRow as ar, type RecordHistoryEntry as as, type RecordScopeContext as at, type ConversationScope as au, type ConversationScopeContext as av, type FieldHistoryEntry as aw, type RestorePreview as ax, type RestoreResult as ay, type CommentThreadRead as az, type TableDuplicateProgress as b, DRILL_DOORS as b$, type WorkDecideManyItem as b0, type WorkDecideMany as b1, type ExternalPrincipalCard as b2, type PublishBinding as b3, type ResolvedPublishBinding as b4, type ResolvedPublishBindingKind as b5, type DecorationPath as b6, type TableDecorations as b7, type GridLayout as b8, type FormulaParse as b9, type AutomationAction as bA, type AutomationFilter as bB, type AutomationItem as bC, type AutomationLastRun as bD, type AutomationRun as bE, type AutomationRunStatus as bF, type AutomationStep as bG, type AutomationTrigger as bH, type AutomationValue as bI, type AutomationValues as bJ, type AutomationWeekday as bK, BUILT_KIND_WORD as bL, CHOICE_NUDGES as bM, type CaptureField as bN, type CaptureQuestion as bO, type ChecklistRequirement as bP, type ChecklistRequirementKind as bQ, type ChecklistRoleSpec as bR, type ChecklistStepSpec as bS, type ChecklistTrigger as bT, type ChecklistTriggerKind as bU, type ChoiceLike as bV, type ChoiceOption as bW, type CustomFieldTableType as bX, DEFAULT_ARCHIVE_LANE as bY, DRILL_CHART_TOKENS as bZ, DRILL_DESCRIPTION_MAX as b_, type FormulaPreview as ba, type RowAction as bb, type ActionRunResult as bc, type AutomationSpec as bd, type AutomationDeclared as be, type AutomationList as bf, type AutomationFlipped as bg, type AutomationRuns as bh, type RecordEvent as bi, type TableWebhookDeclared as bj, type TableWebhook as bk, type IoExportPage as bl, type TableListEntry as bm, type DataHomeTable as bn, type AdminTable as bo, type TableSyncSpec as bp, type TableSyncResult as bq, type TableRowCount as br, type RecordHeader as bs, type OutsideShareAnswer as bt, type ViewOrderSet as bu, ARCHIVE_LANES as bv, ARCHIVE_LANE_LABEL as bw, ARCHIVE_LANE_MEANS as bx, type ActionRefusal as by, type ArchivedDoorRow as bz, type TableDuplicated as c, type ShownTo as c$, DRILL_SCHEMA as c0, type DecorationColor as c1, type DecorationRule as c2, type DecorationRuleOp as c3, type DecorationTarget as c4, type DocSignatureCheck as c5, type DrillAdHocOp as c6, type DrillAnswerRow as c7, type DrillChartToken as c8, type DrillDeclaration as c9, type ImportOutcome as cA, type ImportProposal as cB, PIPELINE_RULE_KINDS as cC, type PipelineMissingField as cD, type PipelineMoveManyResult as cE, type PipelineMoveVerdict as cF, type PipelineRule as cG, type PipelineRuleKind as cH, type PipelineStage as cI, type PublishBindingKind as cJ, ROW_WEB_NOT_READY as cK, type RecordChangeAction as cL, type RecordComment as cM, type RecordScopeComment as cN, type RecordScopeField as cO, type RecordScopeHistoryEntry as cP, type RecordScopeRelation as cQ, type RecordScopeWithheld as cR, type RegisteredTable as cS, type RetypeBehaviour as cT, type RetypePreview as cU, type RowActionStep as cV, SHOWN_TO_LABEL as cW, SHOWN_TO_VALUES as cX, SHOWN_TO_WHO_MAY_CHANGE as cY, STAGE_RULE_ENFORCEMENT as cZ, STAGE_RULE_ON_FAIL as c_, type DrillDimension as ca, type DrillFinding as cb, type DrillGrain as cc, type DrillHaving as cd, type DrillLane as ce, type DrillLevel as cf, type DrillMeasure as cg, type DrillMeasureOp as ch, type DrillMeasureWhereValue as ci, type DrillPath as cj, type DrillRecords as ck, type DrillView as cl, type EnrichAlternate as cm, type EnrichSource as cn, type Enrichment as co, type EntityBackLinkItem as cp, type EntityFieldValue as cq, type EntityRecordMatch as cr, type FieldDriftAspect as cs, type GridLayoutMode as ct, type GridRowHeight as cu, type HistoryActor as cv, type HistoryActorKind as cw, type HistoryChange as cx, type Home as cy, type ImportColumnPlan as cz, type TableCopyInProgress as d, recordsUseSentence as d$, type StageRuleWarning as d0, TABLE_KIND_PREFIX as d1, type TableHomeDestination as d2, type TableLevel as d3, type TableLevelApproval as d4, type TablePlacement as d5, type TablePlacementFact as d6, type TableRenderSchema as d7, type TableSchemaMode as d8, type TableSyncSource as d9, isArchiveLane as dA, isFoundation as dB, isShownTo as dC, isTableKind as dD, isTheChosen as dE, keptGroups as dF, keptOutOfSight as dG, keptTableHref as dH, levelHasShownTo as dI, looksLikeAnId as dJ, mayDrag as dK, moveConsequence as dL, moveInOrder as dM, offeredAsContext as dN, optionKey as dO, optionLabel as dP, parseFieldDrift as dQ, parseTableCopiesInProgress as dR, parseTableDuplicateProgress as dS, parseTableDuplicated as dT, parseTableHome as dU, parseTableMoved as dV, previewRetype as dW, previewRuleChange as dX, recordChangeTrigger as dY, recordSourceKey as dZ, recordSourceTable as d_, type TypedChoiceDecision as da, type ViewLayout as db, type WorkApprovalState as dc, type WorkDecideManyResult as dd, type WorkDecideVerdict as de, type WorkDueState as df, type WorkInboxKind as dg, type WorkOrigin as dh, type WorkTemplateNode as di, type WorkTemplateRelation as dj, actionRefusals as dk, archivedByLine as dl, archivedWhen as dm, asChoiceNudge as dn, choiceSlug as dp, choiceValuesOf as dq, choicesOf as dr, decideTypedChoice as ds, declareDrillDefinition as dt, drillAnswerOf as du, drillFindingKnob as dv, emptyArchiveLine as dw, exportPageXlsx as dx, fieldKindOf as dy, holdsARetiredChoice as dz, type ArchivedRow as e, rehomeSentence as e0, removedChoicesInUse as e1, ruleThatRefuses as e2, rulesWithTopStar as e3, sameDocument as e4, scopeChip as e5, sheetSyncSpec as e6, tableIdOf as e7, tableJsonSchema as e8, tableKindMapping as e9, tableKindSlug as ea, tableRenderSchema as eb, valueConverts as ec, withRowCounts as ed, withTablePlacement as ee, type Table as f, type TableHome as g, type TableMoved as h, type ChoiceUsage as i, type ChoiceRehome as j, type ChoiceCellBack as k, type ChoicesRehomed as l, type TableCapacity as m, type FieldRetyped as n, type TableKindFacts as o, type TableLevelFacts as p, type TableReaderRule as q, type TableLevelSet as r, type EntityFieldsAcross as s, type EntityFieldRights as t, type EntityRecordRead as u, type EntityBackLinks as v, type EntityRowWritten as w, type EntityRecordsFound as x, type PipelineColumn as y, type PipelineVerdict as z };
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 };