@declarion/react 0.48.2 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist-lib/Check-DAfMbQIw.js +38 -0
  2. package/dist-lib/{DraggableChildrenTable-p2ZSdwzj.js → DraggableChildrenTable-B98Md-Yq.js} +30 -30
  3. package/dist-lib/{Grid-CjLFAKMZ.js → Grid-BdtEd4R9.js} +2 -2
  4. package/dist-lib/{LayoutRenderer-DCscqXsv.js → LayoutRenderer-oVU3nEb5.js} +600 -597
  5. package/dist-lib/ListCardsBody-DYMt1H8l.js +287 -0
  6. package/dist-lib/{MarkdownRenderer-Sb7zcvj0.js → MarkdownRenderer-E9hbyoUn.js} +1 -1
  7. package/dist-lib/RefreshControl-B_2eW53M.js +430 -0
  8. package/dist-lib/{SmartDetailPage.impl-BAW-Tx_H.js → SmartDetailPage.impl-Dg22HOxb.js} +520 -515
  9. package/dist-lib/SmartListPage.impl-CPhhXT5S.js +2849 -0
  10. package/dist-lib/{SmartRecordListPage.impl-DtSSlGrI.js → SmartRecordListPage.impl-CF0UKgUj.js} +243 -240
  11. package/dist-lib/SortHeaderMenu-DodGvb7A.js +106 -0
  12. package/dist-lib/action-dispatch-CYOw7nkP.js +1984 -0
  13. package/dist-lib/api/batch.d.ts +5 -2
  14. package/dist-lib/api/data.d.ts +35 -4
  15. package/dist-lib/api/entities.d.ts +3 -3
  16. package/dist-lib/cardProjection-D-AufCh-.js +757 -0
  17. package/dist-lib/components/{shared → actions}/ObjectActionBar.d.ts +1 -1
  18. package/dist-lib/components/{shared → actions}/ResponsiveActionBar.d.ts +1 -1
  19. package/dist-lib/components/fields/cells/factories/date.d.ts +2 -0
  20. package/dist-lib/components/file-widgets/upload.d.ts +6 -1
  21. package/dist-lib/components/layout/Layout.d.ts +1 -1
  22. package/dist-lib/components/layout/TopBar.d.ts +1 -1
  23. package/dist-lib/components/pages/SmartListPage.d.ts +2 -12
  24. package/dist-lib/components/pages/SmartListPage.impl.d.ts +4 -0
  25. package/dist-lib/components/pages/list/ListCardRow.d.ts +40 -0
  26. package/dist-lib/components/pages/list/ListCardsBody.d.ts +34 -0
  27. package/dist-lib/components/pages/list/ListFloatbar.d.ts +1 -1
  28. package/dist-lib/components/pages/list/ListFooter.d.ts +26 -0
  29. package/dist-lib/components/pages/list/ListHeader.d.ts +1 -1
  30. package/dist-lib/components/pages/list/ListNoRows.d.ts +32 -0
  31. package/dist-lib/components/pages/list/ListTable.d.ts +34 -0
  32. package/dist-lib/components/pages/list/ListTableRow.d.ts +18 -0
  33. package/dist-lib/components/pages/list/ListToolbar.d.ts +43 -0
  34. package/dist-lib/components/pages/list/SortHeaderMenu.d.ts +14 -0
  35. package/dist-lib/components/pages/list/page-size.d.ts +3 -0
  36. package/dist-lib/components/pages/list/sortable-header.d.ts +2 -0
  37. package/dist-lib/components/pages/list/useListColumnLayout.d.ts +37 -0
  38. package/dist-lib/components/pages/list/useListQuery.d.ts +66 -0
  39. package/dist-lib/components/pages/list/useListRowInteraction.d.ts +61 -0
  40. package/dist-lib/components/pages/list/useListSelection.d.ts +31 -0
  41. package/dist-lib/components/pages/list/useListSort.d.ts +45 -0
  42. package/dist-lib/components/pages/list/useListViews.d.ts +46 -0
  43. package/dist-lib/components/pages/list/useRowMenu.d.ts +1 -1
  44. package/dist-lib/components/shared/RefreshControl.d.ts +17 -4
  45. package/dist-lib/field-classification-DTgUnbzd.js +1134 -0
  46. package/dist-lib/format-count-DAHCcHZO.js +1551 -0
  47. package/dist-lib/hooks/useBrandingChrome.d.ts +17 -1
  48. package/dist-lib/hooks/useText.d.ts +3 -0
  49. package/dist-lib/hooks/useViews.d.ts +1 -1
  50. package/dist-lib/index.d.ts +17 -15
  51. package/dist-lib/index.js +1783 -6287
  52. package/dist-lib/lib/messages.d.ts +7 -1
  53. package/dist-lib/lib/rowClickGesture.d.ts +12 -0
  54. package/dist-lib/lib/timestamp.d.ts +8 -3
  55. package/dist-lib/peekDraftStore-CnxqkoWN.js +194 -0
  56. package/dist-lib/record-documents-key-DEFlLxnF.js +27 -0
  57. package/dist-lib/registry-WypUQQ7t.js +1768 -0
  58. package/dist-lib/testing.d.ts +17 -2
  59. package/dist-lib/testing.js +72 -58
  60. package/dist-lib/types/api.d.ts +54 -12
  61. package/dist-lib/types/schema.d.ts +22 -6
  62. package/dist-lib/{useCurrentScreen-BshVTPVq.js → useCurrentScreen-C5Oio-1G.js} +1125 -1068
  63. package/dist-lib/useListQuery-Dc2vbxqs.js +87 -0
  64. package/dist-lib/useProperties-C36ENFdY.js +81 -0
  65. package/dist-lib/{useProperties-DrHFr0A1.js → useTabSearchMirror-sIuYEFaq.js} +116 -194
  66. package/dist-lib/{value-B1O6QikE.js → value-igT4LsqW.js} +69 -69
  67. package/package.json +1 -1
  68. package/dist-lib/RefreshControl-Cnl9nE0x.js +0 -945
  69. package/dist-lib/registry-CCxnZW2b.js +0 -5281
  70. /package/dist-lib/components/{shared → actions}/ActionButton.d.ts +0 -0
  71. /package/dist-lib/components/{shared → actions}/ActionDialog.d.ts +0 -0
  72. /package/dist-lib/components/{shared → actions}/ActionResultDialog.d.ts +0 -0
  73. /package/dist-lib/components/{shared → actions}/ActionRunner.d.ts +0 -0
  74. /package/dist-lib/components/{mass-edit → actions}/PropertyGridEditor.d.ts +0 -0
  75. /package/dist-lib/components/{shared → actions}/RowActionsKebab.d.ts +0 -0
  76. /package/dist-lib/components/{shared → chrome}/AssociationTabs.d.ts +0 -0
  77. /package/dist-lib/components/{shared → chrome}/AuditMetaStrip.d.ts +0 -0
  78. /package/dist-lib/components/{shared → chrome}/Breadcrumbs.d.ts +0 -0
  79. /package/dist-lib/components/{shared → chrome}/HighlightsStrip.d.ts +0 -0
  80. /package/dist-lib/components/{shared → chrome}/PageHeader.d.ts +0 -0
  81. /package/dist-lib/components/{shared → chrome}/RecordHeader.d.ts +0 -0
  82. /package/dist-lib/components/{shell → layout}/CommandPalette.d.ts +0 -0
  83. /package/dist-lib/components/{columns → list}/ColumnPicker.d.ts +0 -0
  84. /package/dist-lib/components/{views → list}/ViewSwitcher.d.ts +0 -0
@@ -15,6 +15,8 @@ import type { DataResponse, ListMeta, ListResponse, Refs } from "./types/api";
15
15
  export type ActionResult = ((body: ActionExecuteRequest) => unknown) | Record<string, unknown> | unknown[] | string | number | boolean | null;
16
16
  /** Rows plus optional meta + response-level `$refs` (ref/expanded-column data)
17
17
  * for one entity's list/count fixture. */
18
+ /** One entity's list fixture, or the failure its query returns. */
19
+ export type EntityDataEntry = Record<string, unknown>[] | EntityDataFixture | ListResponse | Error;
18
20
  export interface EntityDataFixture {
19
21
  rows: Record<string, unknown>[];
20
22
  meta?: Partial<ListMeta>;
@@ -23,8 +25,10 @@ export interface EntityDataFixture {
23
25
  export interface RenderWithDeclarionOptions {
24
26
  /** Seeded into the schema query cache so useSchema resolves warm. Build with schemaFixture. */
25
27
  schema?: Schema;
26
- /** entity -> rows, { rows, meta }, or an entityDataFixture() ListResponse; resolves useEntityData / useEntityCount. */
27
- entityData?: Record<string, Record<string, unknown>[] | EntityDataFixture | ListResponse>;
28
+ /** entity -> rows, { rows, meta }, or an entityDataFixture() ListResponse.
29
+ * An Error entry makes the query FAIL; a FUNCTION entry is called with the
30
+ * request, so a filtered query can answer differently from an unfiltered one. */
31
+ entityData?: Record<string, EntityDataEntry | ((params: Record<string, unknown>) => EntityDataEntry)>;
28
32
  /** entity -> { [id]: row | Error }; resolves useObject. Error entries let tests model 404/403 without network. */
29
33
  entityItems?: Record<string, Record<string, Record<string, unknown> | Error>>;
30
34
  /** entity -> { [id]: DataResponse | Error }; resolves useObject when a test needs envelope metadata like `$refs`. */
@@ -43,10 +47,21 @@ export interface RenderWithDeclarionOptions {
43
47
  screenCode?: string;
44
48
  /** Optional responsive viewport seam for component tests that assert phone/tablet behavior. */
45
49
  viewport?: ResponsiveViewport;
50
+ /** Called with every list request before it resolves. A screen decides what
51
+ * to ASK for - which columns, which sort, whether to expand refs - and that
52
+ * is invisible in the rendered output. */
53
+ onListRequest?: (entity: string, params: Record<string, unknown>) => void;
54
+ /** Mounts the screen inside an embed context, as the white-label iframe does:
55
+ * the embed query string the host passes. Absent means the in-app render. */
56
+ embedQuery?: string;
46
57
  }
47
58
  export interface RenderWithDeclarionResult extends RenderResult {
48
59
  /** The live QueryClient, for advanced cache assertions or manual refetch. */
49
60
  queryClient: QueryClient;
61
+ /** Where the screen has navigated to, as `pathname + search + hash`. The
62
+ * alternative is stubbing the navigate hook, which asserts that the screen
63
+ * CALLED something rather than that the user arrived. */
64
+ location: () => string;
50
65
  }
51
66
  /** Build a valid Schema from a partial - fills the required empty maps so a
52
67
  * consumer only declares the entities/screens its test needs. */
@@ -1,12 +1,12 @@
1
- import { Dt as e, Et as t, Ot as n, er as r, jt as i, r as a, t as o, yt as s } from "./useCurrentScreen-BshVTPVq.js";
2
- import { useState as c } from "react";
3
- import { MemoryRouter as l } from "react-router";
4
- import { QueryClient as u, QueryClientProvider as d } from "@tanstack/react-query";
5
- import { Toaster as f } from "sonner";
6
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
7
- import { render as h } from "@testing-library/react";
1
+ import { Dt as e, Et as t, Ot as n, ft as r, jt as i, nr as a, r as o, t as s, yt as c } from "./useCurrentScreen-C5Oio-1G.js";
2
+ import { useState as l } from "react";
3
+ import { MemoryRouter as u, useLocation as d } from "react-router";
4
+ import { QueryClient as f, QueryClientProvider as p } from "@tanstack/react-query";
5
+ import { Toaster as m } from "sonner";
6
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
7
+ import { render as _ } from "@testing-library/react";
8
8
  //#region src/testing.tsx
9
- function g(e = {}) {
9
+ function v(e = {}) {
10
10
  return {
11
11
  languages: [],
12
12
  structures: {},
@@ -19,7 +19,7 @@ function g(e = {}) {
19
19
  ...e
20
20
  };
21
21
  }
22
- function _(e, t = {}, n) {
22
+ function y(e, t = {}, n) {
23
23
  return {
24
24
  data: e,
25
25
  meta: {
@@ -33,27 +33,31 @@ function _(e, t = {}, n) {
33
33
  ...n === void 0 ? {} : { $refs: n }
34
34
  };
35
35
  }
36
- function v(e) {
36
+ function b(e) {
37
37
  return e;
38
38
  }
39
- var y = Symbol("declarion.testing.actionEnvelope");
40
- function b(e) {
39
+ var x = Symbol("declarion.testing.actionEnvelope");
40
+ function S(e) {
41
41
  return {
42
42
  ...e,
43
- [y]: !0
43
+ [x]: !0
44
44
  };
45
45
  }
46
- function x(e) {
47
- if (e && typeof e == "object" && e[y]) {
46
+ function C(e) {
47
+ if (e && typeof e == "object" && e[x]) {
48
48
  let t = { ...e };
49
- return delete t[y], t;
49
+ return delete t[x], t;
50
50
  }
51
51
  return {
52
52
  status: "success",
53
53
  result: e
54
54
  };
55
55
  }
56
- function S() {
56
+ function w({ into: e }) {
57
+ let t = d();
58
+ return e.current = `${t.pathname}${t.search}${t.hash}`, null;
59
+ }
60
+ function T() {
57
61
  let e = {
58
62
  id: "test-tenant",
59
63
  code: "test",
@@ -72,7 +76,7 @@ function S() {
72
76
  };
73
77
  i.getState().setUser(t, e);
74
78
  }
75
- function C(e) {
79
+ function E(e) {
76
80
  if (e === void 0) return { rows: [] };
77
81
  if (Array.isArray(e)) return { rows: e };
78
82
  if (Array.isArray(e.data)) {
@@ -85,46 +89,50 @@ function C(e) {
85
89
  }
86
90
  return e;
87
91
  }
88
- function w(r) {
92
+ function D(r) {
89
93
  let i = r.entityData ?? {};
90
94
  n((e, t) => {
91
- let n = i[e], r = C(n), a = r.meta?.per_page ?? 50, o = r.meta?.total ?? r.rows.length;
95
+ let n = t;
96
+ r.onListRequest?.(e, n);
97
+ let a = i[e], o = typeof a == "function" ? a(n) : a;
98
+ if (o instanceof Error) throw o;
99
+ let s = E(o), c = s.meta?.per_page ?? 50, l = s.meta?.total ?? s.rows.length;
92
100
  return t.count === "only" ? {
93
101
  data: [],
94
102
  meta: {
95
103
  page: 1,
96
- per_page: a,
97
- total: o,
98
- total_pages: r.meta?.total_pages ?? Math.max(1, Math.ceil(o / a)),
99
- count_mode: r.meta?.count_mode ?? "exact"
104
+ per_page: c,
105
+ total: l,
106
+ total_pages: s.meta?.total_pages ?? Math.max(1, Math.ceil(l / c)),
107
+ count_mode: s.meta?.count_mode ?? "exact"
100
108
  }
101
109
  } : {
102
- data: r.rows,
110
+ data: s.rows,
103
111
  meta: {
104
- page: r.meta?.page ?? 1,
105
- per_page: a,
106
- has_more: r.meta?.has_more ?? !1
112
+ page: s.meta?.page ?? 1,
113
+ per_page: c,
114
+ has_more: s.meta?.has_more ?? !1
107
115
  },
108
- ...r.refs === void 0 ? {} : { $refs: r.refs }
116
+ ...s.refs === void 0 ? {} : { $refs: s.refs }
109
117
  };
110
118
  });
111
119
  let a = r.entityItems ?? {}, o = r.entityItemResponses ?? {};
112
120
  e((e, t) => {
113
- let n = typeof t == "string" ? t : s(t), r = o[e]?.[n];
121
+ let n = typeof t == "string" ? t : c(t), r = o[e]?.[n];
114
122
  if (r instanceof Error) throw r;
115
123
  if (r !== void 0) return r;
116
124
  let i = a[e]?.[n];
117
125
  if (i instanceof Error) throw i;
118
126
  return { data: i };
119
127
  });
120
- let c = r.actionResults ?? {};
128
+ let s = r.actionResults ?? {};
121
129
  t(async (e, t) => {
122
- if (!(e in c)) throw Error(`renderWithDeclarion: no action result registered for "${e}" (seed it via actionResults)`);
123
- let n = c[e];
124
- return x(typeof n == "function" ? await n(t) : n);
130
+ if (!(e in s)) throw Error(`renderWithDeclarion: no action result registered for "${e}" (seed it via actionResults)`);
131
+ let n = s[e];
132
+ return C(typeof n == "function" ? await n(t) : n);
125
133
  });
126
134
  }
127
- function T() {
135
+ function O() {
128
136
  n(null), e(null), t(null), i.setState({
129
137
  user: null,
130
138
  isAuthenticated: !1,
@@ -132,48 +140,54 @@ function T() {
132
140
  tenants: []
133
141
  });
134
142
  }
135
- function E(e, t = {}) {
136
- let n = new u({ defaultOptions: { queries: {
143
+ function k(e, t = {}) {
144
+ let n = new f({ defaultOptions: { queries: {
137
145
  retry: !1,
138
146
  gcTime: Infinity
139
147
  } } });
140
- S(), n.setQueryData(["schema", !0], t.schema ?? g()), w(t);
141
- let i = t.screenCode ? /* @__PURE__ */ p(o, {
148
+ T(), n.setQueryData(["schema", !0], t.schema ?? v()), D(t);
149
+ let i = t.screenCode ? /* @__PURE__ */ h(s, {
142
150
  code: t.screenCode,
143
151
  children: e
144
- }) : e, s = /* @__PURE__ */ m(d, {
152
+ }) : e, c = { current: t.route ?? "/" }, l = /* @__PURE__ */ g(p, {
145
153
  client: n,
146
- children: [/* @__PURE__ */ p(l, {
154
+ children: [/* @__PURE__ */ g(u, {
147
155
  initialEntries: [t.route ?? "/"],
148
- children: /* @__PURE__ */ p(a, { children: i })
149
- }), /* @__PURE__ */ p(f, {})]
150
- }), c = h(t.viewport ? /* @__PURE__ */ p(r, {
156
+ children: [/* @__PURE__ */ h(w, { into: c }), /* @__PURE__ */ h(o, { children: i })]
157
+ }), /* @__PURE__ */ h(m, {})]
158
+ }), d = t.embedQuery ? /* @__PURE__ */ h(r, {
159
+ query: t.embedQuery,
160
+ children: l
161
+ }) : l, y = _(t.viewport ? /* @__PURE__ */ h(a, {
151
162
  viewportOverride: t.viewport,
152
- children: s
153
- }) : s);
154
- return Object.assign(c, { queryClient: n });
163
+ children: d
164
+ }) : d);
165
+ return Object.assign(y, {
166
+ queryClient: n,
167
+ location: () => c.current
168
+ });
155
169
  }
156
- function D({ children: e, authenticated: t = !0, ...n }) {
157
- let [r] = c(() => {
158
- let e = new u({ defaultOptions: { queries: {
170
+ function A({ children: e, authenticated: t = !0, ...n }) {
171
+ let [r] = l(() => {
172
+ let e = new f({ defaultOptions: { queries: {
159
173
  retry: !1,
160
174
  gcTime: Infinity
161
175
  } } });
162
- return t ? (S(), e.setQueryData(["schema", !0], n.schema ?? g())) : i.setState({
176
+ return t ? (T(), e.setQueryData(["schema", !0], n.schema ?? v())) : i.setState({
163
177
  user: null,
164
178
  isAuthenticated: !1,
165
179
  activeTenant: null,
166
180
  tenants: []
167
- }), w(n), e;
181
+ }), D(n), e;
168
182
  });
169
- return /* @__PURE__ */ m(d, {
183
+ return /* @__PURE__ */ g(p, {
170
184
  client: r,
171
- children: [/* @__PURE__ */ p(l, {
185
+ children: [/* @__PURE__ */ h(u, {
172
186
  initialEntries: [n.route ?? "/"],
173
- children: /* @__PURE__ */ p(a, { children: e })
174
- }), /* @__PURE__ */ p(f, {})]
187
+ children: /* @__PURE__ */ h(o, { children: e })
188
+ }), /* @__PURE__ */ h(m, {})]
175
189
  });
176
190
  }
177
- typeof afterEach == "function" && afterEach(() => T());
191
+ typeof afterEach == "function" && afterEach(() => O());
178
192
  //#endregion
179
- export { D as PreviewHarness, b as actionEnvelope, v as actionResults, T as cleanupDeclarion, _ as entityDataFixture, E as renderWithDeclarion, g as schemaFixture };
193
+ export { A as PreviewHarness, S as actionEnvelope, b as actionResults, O as cleanupDeclarion, y as entityDataFixture, k as renderWithDeclarion, v as schemaFixture };
@@ -33,24 +33,50 @@ export interface DataResponse<T = Record<string, unknown>> {
33
33
  data: T;
34
34
  $refs?: Refs;
35
35
  }
36
+ /**
37
+ * A failure, in RFC 9457 Problem Details form - the one shape every Declarion
38
+ * carrier sends. `type` is the identifier to branch on; its last path segment is
39
+ * identical in every deployment. `title` is the sentence to SHOW: the server
40
+ * already rendered it in this caller's language, and the browser holds no
41
+ * catalogue to render one itself. A type's declared members are TOP-LEVEL, which
42
+ * is why this is an index signature and not a fixed shape.
43
+ */
36
44
  export interface ApiErrorBody {
37
- error: {
38
- message: string;
39
- code: string;
40
- field?: string;
41
- };
42
- /** Bulk operation item index (present on validation errors for array requests). */
43
- index?: number;
45
+ type: string;
46
+ status?: number;
47
+ title: string;
48
+ /** This occurrence. A DIAGNOSTIC, not the headline - and absent for a failure nothing recognised. */
49
+ detail?: string;
50
+ instance?: string;
51
+ retryable: boolean;
52
+ [member: string]: unknown;
44
53
  }
45
54
  export declare class ApiError extends Error {
46
55
  status: number;
56
+ /** The identifier to compare - the type's last path segment, e.g. `entity.not_found`. */
47
57
  code: string;
58
+ /** The full `type`, e.g. `/errors/entity.not_found`. */
59
+ type: string;
60
+ /** Whether the same call can succeed later. From the DECLARATION, never computed from a status. */
61
+ retryable: boolean;
62
+ /** The diagnostic for this occurrence. Never the headline a user reads. */
63
+ detail?: string;
48
64
  /** Bulk operation item index (present on validation errors for array requests). */
49
65
  index?: number;
50
- /** Raw JSON body for endpoints that return a non-standard error envelope (e.g. invoke:each batch). */
66
+ /** The untouched body, so a caller can re-detect a shape this class does not model. */
51
67
  raw?: unknown;
52
- constructor(status: number, message: string, code: string, index?: number, raw?: unknown);
68
+ constructor(status: number, body: Partial<ApiErrorBody>, raw?: unknown);
69
+ /**
70
+ * A declared member of this error's type. ONE accessor, so the six known
71
+ * consumers (`constraint`, `row_version`, `did_you_mean`, `valid_parameters`,
72
+ * `threshold`, `width`) do not each invent an access pattern.
73
+ */
74
+ ext<T = unknown>(member: string): T | undefined;
53
75
  }
76
+ /** The comparable identifier inside a `type`: its last path segment. */
77
+ export declare function errorCodeOf(type: string | undefined): string;
78
+ /** Whether a parsed JSON body is the platform's error object. */
79
+ export declare function isApiErrorBody(body: unknown): body is ApiErrorBody;
54
80
  /**
55
81
  * Stable error codes for cursor-based list pagination. The server returns
56
82
  * these on ValidationError{Field:"after"} when an `after` token cannot be
@@ -68,15 +94,15 @@ export declare class ApiError extends Error {
68
94
  * direct apiFetch callers can recognise these codes to drive their own
69
95
  * retry logic.
70
96
  */
71
- export declare const CURSOR_SEMANTICS_MISMATCH = "cursor_semantics_mismatch";
72
- export declare const CURSOR_LOCALE_CHANGED = "cursor_locale_changed";
97
+ export declare const CURSOR_SEMANTICS_MISMATCH = "cursor.semantics_mismatch";
98
+ export declare const CURSOR_LOCALE_CHANGED = "cursor.locale_changed";
73
99
  /**
74
100
  * A cross-store (Postgres-hot / ClickHouse-cold) archive cursor that the server
75
101
  * could not decode for this read - a malformed token, a tenant/entity mismatch,
76
102
  * or a retired bespoke-archive cursor minted before the native-cursor release.
77
103
  * Same recovery contract as the other two: drop `after`, refetch window 1.
78
104
  */
79
- export declare const ARCHIVE_CURSOR_INVALID = "archive_cursor_invalid";
105
+ export declare const ARCHIVE_CURSOR_INVALID = "cursor.archive_invalid";
80
106
  /** True if the error is a recoverable cursor-stale signal that warrants
81
107
  * refetching page 1 instead of surfacing to the user. */
82
108
  export declare function isCursorStaleError(err: unknown): boolean;
@@ -533,3 +559,19 @@ export interface EnrichedRow extends RowData {
533
559
  $units?: Units;
534
560
  $evidence?: EvidenceVerdict;
535
561
  }
562
+ /** readProblem is the ONE way this client reads a failing response.
563
+ *
564
+ * It always consumes the body, even where only the status is acted on: an
565
+ * unread body leaves its stream - and the connection under it - open in the
566
+ * browser until garbage collection, and a page holding one never reaches
567
+ * network idle. A `/reset` page sat with one open refresh response for exactly
568
+ * that reason.
569
+ *
570
+ * `raw` is the untouched body, which the batch re-detection still needs; `body`
571
+ * is it only when it IS the error object. Two top-level shapes arrive here: a
572
+ * flat error object HAS a `type`, and a processed batch result
573
+ * (`{status, success, errors}`) is deliberately not an error. */
574
+ export declare function readProblem(res: Response): Promise<{
575
+ raw: unknown;
576
+ body: Partial<ApiErrorBody>;
577
+ }>;
@@ -102,6 +102,15 @@ export interface EntityField {
102
102
  */
103
103
  name?: string;
104
104
  type: string;
105
+ /**
106
+ * Computed and stamped by the server: whether a CROSS-store read can order by
107
+ * this field. Meaningful only where the entity's list_pagination is "cursor".
108
+ * Asked rather than re-derived here - a second copy of the backend's type
109
+ * allowlist drifts the day either side moves, and the symptom is an operator
110
+ * clicking a column header and getting a raw backend error in place of the
111
+ * table.
112
+ */
113
+ cross_store_sortable?: boolean;
105
114
  required?: boolean;
106
115
  primary?: boolean;
107
116
  auto?: boolean;
@@ -1018,7 +1027,6 @@ export interface HandlerDef {
1018
1027
  icon?: string;
1019
1028
  };
1020
1029
  params?: OrderedMap<HandlerParam>;
1021
- success_event?: string;
1022
1030
  }
1023
1031
  export interface Schema {
1024
1032
  languages: LanguageDef[];
@@ -1031,6 +1039,16 @@ export interface Schema {
1031
1039
  enums: Record<string, EnumDef>;
1032
1040
  parameters: Record<string, ParameterDef>;
1033
1041
  messages?: Record<string, LocalizedString>;
1042
+ /**
1043
+ * Declared error types, code -> title per language. For rendering a STORED
1044
+ * code - on an agent turn, a job row, an audit row - in the reader's
1045
+ * language. An error answering a request carries its own title in the
1046
+ * response and needs none of this.
1047
+ *
1048
+ * Errors are NEVER declared under `messages`: a failure has a type, and a
1049
+ * type has a title.
1050
+ */
1051
+ errors?: Record<string, LocalizedString>;
1034
1052
  areas?: AreaDef[];
1035
1053
  accents?: Record<string, AccentDef>;
1036
1054
  /**
@@ -1062,11 +1080,9 @@ export interface ClassificationTierDef {
1062
1080
  audit_on_read?: boolean;
1063
1081
  icon?: string;
1064
1082
  /**
1065
- * When true, the tier triggers stricter SoD controls: superadmin
1066
- * reveals emit a distinct audit code, tenant param
1067
- * `auth.superadmin_classification_bypass=false` disables the
1068
- * implicit bypass, role self-assignment is refused, transitive role
1069
- * inheritance is hard-errored at load. Plan §11 Decisions Log #20-22.
1083
+ * When true, the tier triggers stricter SoD controls: a platform owner's
1084
+ * reveal emits a distinct audit code, role self-assignment is refused, and
1085
+ * transitive role inheritance is hard-errored at load.
1070
1086
  */
1071
1087
  sod_protected?: boolean;
1072
1088
  }