@dashai/sdk 0.10.0 → 2.0.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 (52) hide show
  1. package/README.md +53 -13
  2. package/dist/auth/client.cjs +23 -1
  3. package/dist/auth/client.cjs.map +1 -1
  4. package/dist/auth/client.d.cts +30 -5
  5. package/dist/auth/client.d.ts +30 -5
  6. package/dist/auth/client.js +23 -1
  7. package/dist/auth/client.js.map +1 -1
  8. package/dist/auth/middleware.cjs +11 -1
  9. package/dist/auth/middleware.cjs.map +1 -1
  10. package/dist/auth/middleware.js +11 -1
  11. package/dist/auth/middleware.js.map +1 -1
  12. package/dist/auth/server.cjs +36 -7
  13. package/dist/auth/server.cjs.map +1 -1
  14. package/dist/auth/server.js +36 -7
  15. package/dist/auth/server.js.map +1 -1
  16. package/dist/auth/types.cjs.map +1 -1
  17. package/dist/auth/types.d.cts +13 -0
  18. package/dist/auth/types.d.ts +13 -0
  19. package/dist/auth/types.js.map +1 -1
  20. package/dist/deps/index.cjs +82 -7
  21. package/dist/deps/index.cjs.map +1 -1
  22. package/dist/deps/index.d.cts +28 -10
  23. package/dist/deps/index.d.ts +28 -10
  24. package/dist/deps/index.js +81 -8
  25. package/dist/deps/index.js.map +1 -1
  26. package/dist/index-BsSFz58g.d.cts +431 -0
  27. package/dist/index-BsSFz58g.d.ts +431 -0
  28. package/dist/index.cjs +218 -23
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +66 -53
  31. package/dist/index.d.ts +66 -53
  32. package/dist/index.js +213 -24
  33. package/dist/index.js.map +1 -1
  34. package/dist/query/index.cjs +158 -2
  35. package/dist/query/index.cjs.map +1 -1
  36. package/dist/query/index.d.cts +7 -7
  37. package/dist/query/index.d.ts +7 -7
  38. package/dist/query/index.js +158 -2
  39. package/dist/query/index.js.map +1 -1
  40. package/dist/react/index.d.cts +1 -1
  41. package/dist/react/index.d.ts +1 -1
  42. package/dist/{types-BwlzFHbq.d.cts → types-CkAfiS4k.d.cts} +37 -31
  43. package/dist/{types-BwlzFHbq.d.ts → types-CkAfiS4k.d.ts} +37 -31
  44. package/dist/uses/index.cjs +147 -0
  45. package/dist/uses/index.cjs.map +1 -0
  46. package/dist/uses/index.d.cts +1 -0
  47. package/dist/uses/index.d.ts +1 -0
  48. package/dist/uses/index.js +142 -0
  49. package/dist/uses/index.js.map +1 -0
  50. package/package.json +6 -1
  51. package/dist/errors-BV75u7b9.d.cts +0 -207
  52. package/dist/errors-BV75u7b9.d.ts +0 -207
@@ -0,0 +1,431 @@
1
+ /**
2
+ * Error model for @dashai/sdk.
3
+ *
4
+ * The backend speaks a structured error envelope:
5
+ *
6
+ * {
7
+ * "code": "ROW_NOT_FOUND",
8
+ * "message": "Row 123 not found in tasks",
9
+ * "retriable": false,
10
+ * "context": { ... }
11
+ * }
12
+ *
13
+ * This module wraps that envelope in a typed `DashwiseError` plus a small
14
+ * set of subclasses for the codes consumers most commonly want to branch
15
+ * on (network errors, auth failures, row-not-found, contract violations).
16
+ *
17
+ * Anything not matched by a specific subclass becomes a plain
18
+ * `DashwiseError` carrying the raw `code`. Branch on `.code` for codes
19
+ * we don't have a class for; use `instanceof` for the common cases.
20
+ */
21
+ /**
22
+ * Known error codes. Not exhaustive — the backend emits many codes
23
+ * specific to individual modules / endpoints. Use these constants when
24
+ * you want compile-time safety; otherwise treat `err.code` as a string.
25
+ *
26
+ * The list is curated to the codes a module author is most likely to
27
+ * branch on. Adding a new code here is a non-breaking change.
28
+ */
29
+ declare const DashwiseErrorCode: {
30
+ readonly UNAUTHENTICATED: "UNAUTHENTICATED";
31
+ readonly FORBIDDEN: "FORBIDDEN";
32
+ readonly TOKEN_EXPIRED: "TOKEN_EXPIRED";
33
+ readonly INSTALLATION_NOT_FOUND: "INSTALLATION_NOT_FOUND";
34
+ readonly INSTALLATION_MODE_UNSUPPORTED: "INSTALLATION_MODE_UNSUPPORTED";
35
+ readonly CONTRACT_VIOLATION: "CONTRACT_VIOLATION";
36
+ readonly FIELD_NOT_READABLE: "FIELD_NOT_READABLE";
37
+ readonly FILTER_OP_UNKNOWN: "FILTER_OP_UNKNOWN";
38
+ readonly OPERATION_NOT_ALLOWED: "OPERATION_NOT_ALLOWED";
39
+ readonly DEPENDENCY_NOT_DECLARED: "DEPENDENCY_NOT_DECLARED";
40
+ readonly TABLE_NOT_IN_CONTRACT: "TABLE_NOT_IN_CONTRACT";
41
+ readonly PROVIDER_TABLE_MISSING: "PROVIDER_TABLE_MISSING";
42
+ readonly OPERATION_NOT_ALLOWED_BY_PROVIDER: "OPERATION_NOT_ALLOWED_BY_PROVIDER";
43
+ readonly DEP_UNBOUND: "DEP_UNBOUND";
44
+ readonly USES_UNBOUND: "USES_UNBOUND";
45
+ readonly USES_OP_NOT_ALLOWED: "USES_OP_NOT_ALLOWED";
46
+ readonly CONTRACT_FIELD_MISSING: "CONTRACT_FIELD_MISSING";
47
+ readonly USES_JOIN_UNSUPPORTED: "USES_JOIN_UNSUPPORTED";
48
+ readonly LINK_FIELD_NOT_FOUND: "LINK_FIELD_NOT_FOUND";
49
+ readonly NOT_A_LINK_FIELD: "NOT_A_LINK_FIELD";
50
+ readonly JOIN_NOT_LINKED: "JOIN_NOT_LINKED";
51
+ readonly ACTION_NOT_EXPOSED: "ACTION_NOT_EXPOSED";
52
+ readonly ACTION_NOT_DECLARED: "ACTION_NOT_DECLARED";
53
+ readonly ACTION_INPUT_INVALID: "ACTION_INPUT_INVALID";
54
+ readonly ACTION_OUTPUT_INVALID: "ACTION_OUTPUT_INVALID";
55
+ readonly ACTION_RATE_LIMITED: "ACTION_RATE_LIMITED";
56
+ readonly ACTION_EXECUTION_FAILED: "ACTION_EXECUTION_FAILED";
57
+ readonly ROW_NOT_FOUND: "ROW_NOT_FOUND";
58
+ readonly TABLE_NOT_FOUND: "TABLE_NOT_FOUND";
59
+ readonly VALIDATION_FAILED: "VALIDATION_FAILED";
60
+ readonly ROW_LIMIT_EXCEEDED: "ROW_LIMIT_EXCEEDED";
61
+ readonly STORAGE_LIMIT_EXCEEDED: "STORAGE_LIMIT_EXCEEDED";
62
+ readonly OUTBOUND_NOT_ALLOWED: "OUTBOUND_NOT_ALLOWED";
63
+ readonly OUTBOUND_CONCURRENCY_LIMITED: "OUTBOUND_CONCURRENCY_LIMITED";
64
+ readonly NETWORK_ERROR: "NETWORK_ERROR";
65
+ readonly TIMEOUT: "TIMEOUT";
66
+ readonly INTERNAL_ERROR: "INTERNAL_ERROR";
67
+ };
68
+ type DashwiseErrorCode = (typeof DashwiseErrorCode)[keyof typeof DashwiseErrorCode];
69
+ /**
70
+ * Base class for every error thrown by @dashai/sdk. Carries the
71
+ * structured envelope from the backend (or a synthetic one for
72
+ * client-side failures like network errors / timeouts).
73
+ *
74
+ * Always thrown — never returned as a value. The async client methods
75
+ * `.list()` / `.get()` etc. reject with one of these on failure.
76
+ */
77
+ declare class DashwiseError extends Error {
78
+ readonly code: string;
79
+ readonly status: number;
80
+ readonly retriable: boolean;
81
+ readonly context: Record<string, unknown> | undefined;
82
+ /**
83
+ * Backend-issued trace anchor (Phase 6 slice 6.2, 2026-05-19).
84
+ * Mirrors the `x-request-id` response header. Populated whenever
85
+ * the backend's `RuntimeQueryController` (or any future endpoint
86
+ * that echoes the header) is the origin of this error. `null` when
87
+ * the failure is client-side (NetworkError / TimeoutError — the
88
+ * request never reached the server, so there's no server-issued
89
+ * ID to surface).
90
+ *
91
+ * Use this as a debugging trace anchor when filing a bug against a
92
+ * specific failed query — the matching row in `module_query_log`
93
+ * carries the full backend context (ast_hash, error_code,
94
+ * duration_ms, etc.).
95
+ */
96
+ readonly requestId: string | null;
97
+ constructor(code: string, message: string, options?: {
98
+ status?: number;
99
+ retriable?: boolean;
100
+ context?: Record<string, unknown>;
101
+ cause?: unknown;
102
+ /**
103
+ * Phase 6 slice 6.2: backend `x-request-id` response header,
104
+ * captured by the transport before throwing. Pass `undefined`
105
+ * (or omit) for client-side errors that never hit the server.
106
+ */
107
+ requestId?: string | null;
108
+ });
109
+ }
110
+ /** Network-level failure (DNS, connection refused, TLS, fetch threw). */
111
+ declare class NetworkError extends DashwiseError {
112
+ constructor(message: string, cause?: unknown);
113
+ }
114
+ /** Request exceeded the configured timeout (`timeoutMs`). */
115
+ declare class TimeoutError extends DashwiseError {
116
+ constructor(message: string, timeoutMs: number);
117
+ }
118
+ /** 401 — token missing/invalid. */
119
+ declare class UnauthenticatedError extends DashwiseError {
120
+ constructor(message?: string, requestId?: string | null);
121
+ }
122
+ /** 403 — caller lacks the role/scope for this operation. */
123
+ declare class ForbiddenError extends DashwiseError {
124
+ constructor(message: string, context?: Record<string, unknown>, requestId?: string | null);
125
+ }
126
+ /** 404 — `GET /db/<table>/<id>` for a missing or soft-deleted row. */
127
+ declare class RowNotFoundError extends DashwiseError {
128
+ constructor(message: string, context?: Record<string, unknown>, requestId?: string | null);
129
+ }
130
+ /**
131
+ * Schema-level rejection: dep contract violated, table not exposed, field
132
+ * not readable, filter op not allowed. Covers the family of "you asked for
133
+ * something the manifest doesn't permit" errors.
134
+ */
135
+ declare class ContractViolationError extends DashwiseError {
136
+ constructor(message: string, context?: Record<string, unknown>, requestId?: string | null);
137
+ }
138
+ /** 422-ish — request body failed validation. Inspect `context` for field-level errors. */
139
+ declare class ValidationError extends DashwiseError {
140
+ constructor(message: string, context?: Record<string, unknown>, requestId?: string | null);
141
+ }
142
+ /**
143
+ * 404 — the caller's `module.json#dependencies` doesn't declare a
144
+ * dependency on the requested provider module, OR the declared dep
145
+ * exists but its `reads[]` block doesn't include the requested table.
146
+ *
147
+ * Either way the fix is on the **caller's** side: update the manifest
148
+ * to declare the dep / add the table to `reads[]`, then re-publish.
149
+ *
150
+ * Covers both `DEPENDENCY_NOT_DECLARED` and `TABLE_NOT_IN_CONTRACT` —
151
+ * inspect `err.code` to distinguish if you need different UX per case.
152
+ */
153
+ declare class DependencyContractError extends DashwiseError {
154
+ constructor(code: string, message: string, context?: Record<string, unknown>, requestId?: string | null);
155
+ }
156
+ /**
157
+ * 404 — the provider's physical table no longer exists. This means the
158
+ * provider published a version that dropped the table while the
159
+ * consumer's installation still pinned the old contract. Recovery is
160
+ * on the **provider's** side (republish with the table) or the
161
+ * workspace admin's (downgrade the provider, or upgrade the consumer
162
+ * to a version whose `dependencies[]` no longer references it).
163
+ */
164
+ declare class ProviderTableMissingError extends DashwiseError {
165
+ constructor(message: string, context?: Record<string, unknown>, requestId?: string | null);
166
+ }
167
+ /**
168
+ * 403 — the provider's `exposes.operations.<verb>.allowed` is explicitly
169
+ * `false` for the requested verb. Distinct from `OPERATION_NOT_ALLOWED`
170
+ * (which is the **owner's** own-table policy) — `OPERATION_NOT_ALLOWED_BY_PROVIDER`
171
+ * is the provider opting out of letting depending modules use a verb.
172
+ *
173
+ * No caller-side fix; either the provider needs to flip the gate, or
174
+ * the consumer needs to find a different way to satisfy the use case.
175
+ */
176
+ declare class OperationNotAllowedByProviderError extends DashwiseError {
177
+ constructor(message: string, context?: Record<string, unknown>, requestId?: string | null);
178
+ }
179
+ /**
180
+ * The vocabulary of `unbound_reason` values a parked dependency can
181
+ * carry, surfaced in {@link DepUnboundError.reason}. Mirrors the
182
+ * backend's `module_dependencies.unbound_reason` enum (Phase 3
183
+ * modules-platform-v2). Not exhaustive by design — treat `.reason` as a
184
+ * string and branch on these constants when you want compile-time
185
+ * safety. Adding a new reason is a non-breaking change.
186
+ *
187
+ * Resolve/bind-time reasons (why the dep never bound):
188
+ * - `MISSING_DEPENDENCY` no install of the provider module in the workspace
189
+ * - `DEPENDENCY_VERSION_MISMATCH` an install exists but its version is outside the declared range
190
+ * - `PROVIDER_VERSION_RECORD_MISSING` the provider's version row is gone (data-integrity edge)
191
+ * - `EXPOSES_MISSING` the provider no longer exposes a table/field the dep reads
192
+ * - `EXPOSES_PRIVATE` the exposed surface is `private` to the consumer
193
+ * - `ACTION_NOT_EXPOSED` a declared dep action isn't exposed by the provider (Rule #11)
194
+ * - `PROVIDER_NOT_PRODUCTION` kind hygiene: a production consumer can only bind a production provider
195
+ *
196
+ * Lifecycle reasons (the dep bound once, then got parked):
197
+ * - `MANUALLY_UNBOUND` a workspace admin ran `deps unbind` / the unbind endpoint
198
+ * - `PROVIDER_UPGRADE_BROKE_CONTRACT` a provider upgrade (with `force`) broke this consumer's contract
199
+ * - `PROVIDER_UNINSTALLED` the provider was uninstalled with `park_consumers`
200
+ */
201
+ declare const DepUnboundReason: {
202
+ readonly MISSING_DEPENDENCY: "MISSING_DEPENDENCY";
203
+ readonly DEPENDENCY_VERSION_MISMATCH: "DEPENDENCY_VERSION_MISMATCH";
204
+ readonly PROVIDER_VERSION_RECORD_MISSING: "PROVIDER_VERSION_RECORD_MISSING";
205
+ readonly EXPOSES_MISSING: "EXPOSES_MISSING";
206
+ readonly EXPOSES_PRIVATE: "EXPOSES_PRIVATE";
207
+ readonly ACTION_NOT_EXPOSED: "ACTION_NOT_EXPOSED";
208
+ readonly PROVIDER_NOT_PRODUCTION: "PROVIDER_NOT_PRODUCTION";
209
+ readonly MANUALLY_UNBOUND: "MANUALLY_UNBOUND";
210
+ readonly PROVIDER_UPGRADE_BROKE_CONTRACT: "PROVIDER_UPGRADE_BROKE_CONTRACT";
211
+ readonly PROVIDER_UNINSTALLED: "PROVIDER_UNINSTALLED";
212
+ };
213
+ type DepUnboundReason = (typeof DepUnboundReason)[keyof typeof DepUnboundReason];
214
+ /**
215
+ * 409 — a runtime read (borrowed-table `list` / `get`, query-plane
216
+ * `qb.deps.<slug>.<table>`, or a cross-module action) targeted a
217
+ * dependency whose `module_dependencies` row is `status='unbound'`
218
+ * (Phase 3 modules-platform-v2 dependency connect lifecycle).
219
+ *
220
+ * "Unbound" means the dependency is *declared* in the consumer's
221
+ * manifest but not *connected* to a provider installation. It happens
222
+ * when the resolver PARKED the dep at install/apply time (no provider
223
+ * in the workspace, version mismatch, exposes/action coverage gap) or
224
+ * when the dependency was later parked (manually unbound, provider
225
+ * upgrade broke the contract, provider uninstalled).
226
+ *
227
+ * This is a *recoverable* state, not a bug in the consumer. Catch it and
228
+ * render a "connect your provider" prompt — a workspace admin resolves it
229
+ * by installing/binding the provider (`dashwise deps bind <slug>` or the
230
+ * `POST /api/installations/:id/dependencies/:providerSlug/bind` endpoint).
231
+ * Once bound, the same read succeeds with no code change.
232
+ *
233
+ * Convenience accessors ({@link DepUnboundError.provider},
234
+ * {@link DepUnboundError.range}, {@link DepUnboundError.reason}) read the
235
+ * backend's `context: { provider, range, reason }` so callers don't have
236
+ * to reach into `err.context` by hand.
237
+ *
238
+ * @example
239
+ * ```ts
240
+ * import { DepUnboundError } from '@dashai/sdk';
241
+ *
242
+ * try {
243
+ * const contacts = await client.deps('crm').db<ContactRow>('contacts').list();
244
+ * // …or the typed builder: await qb.deps.crm.contacts.execute();
245
+ * } catch (err) {
246
+ * if (err instanceof DepUnboundError) {
247
+ * // Declared but not connected — show a connect-your-provider CTA.
248
+ * return <ConnectProvider provider={err.provider} range={err.range} reason={err.reason} />;
249
+ * }
250
+ * throw err;
251
+ * }
252
+ * ```
253
+ */
254
+ declare class DepUnboundError extends DashwiseError {
255
+ constructor(message: string, context?: Record<string, unknown>, requestId?: string | null);
256
+ /**
257
+ * The provider module slug the parked dependency points at (kebab-case,
258
+ * e.g. `crm`). Read from `context.provider`; `undefined` if the backend
259
+ * omitted it.
260
+ */
261
+ get provider(): string | undefined;
262
+ /**
263
+ * The SemVer range the consumer's manifest declared for this dependency
264
+ * (e.g. `^1.2.0`). Read from `context.range`; `undefined` if omitted.
265
+ */
266
+ get range(): string | undefined;
267
+ /**
268
+ * Why the dependency is unbound — one of {@link DepUnboundReason} (but
269
+ * typed as `string` for forward-compat with reasons the backend may add).
270
+ * Read from `context.reason`; `undefined` if omitted.
271
+ */
272
+ get reason(): string | undefined;
273
+ }
274
+ /**
275
+ * The vocabulary of `reason` values a parked `uses` binding can carry,
276
+ * surfaced in {@link UsesUnboundError.reason}. Mirrors the backend's
277
+ * `module_table_bindings` unbound_reason enum for this plane
278
+ * (Phase 4 modules-platform-v2). Not exhaustive by design — treat
279
+ * `.reason` as a string; branch on these constants for compile-time
280
+ * safety. Adding a new reason is non-breaking.
281
+ *
282
+ * - `NOT_BOUND_YET` the slot has never been bound (declared
283
+ * but no workspace table connected yet)
284
+ * - `AMBIGUOUS_MATCH` auto-match found >1 candidate table; a
285
+ * human must pick one (`dashwise bind`)
286
+ * - `NO_MATCH` auto-match found no candidate table
287
+ * - `TABLE_DELETED` the bound table was trashed (or a mapped
288
+ * field drifted away) → the row parked
289
+ * - `OPS_WIDENED_PENDING_CONSENT` the manifest widened `ops` beyond what
290
+ * was consented at bind time; re-bind to
291
+ * refresh consent
292
+ * - `MANUALLY_UNBOUND` a workspace admin ran `dashwise unbind`
293
+ */
294
+ declare const UsesUnboundReason: {
295
+ readonly NOT_BOUND_YET: "NOT_BOUND_YET";
296
+ readonly AMBIGUOUS_MATCH: "AMBIGUOUS_MATCH";
297
+ readonly NO_MATCH: "NO_MATCH";
298
+ readonly TABLE_DELETED: "TABLE_DELETED";
299
+ readonly OPS_WIDENED_PENDING_CONSENT: "OPS_WIDENED_PENDING_CONSENT";
300
+ readonly MANUALLY_UNBOUND: "MANUALLY_UNBOUND";
301
+ };
302
+ type UsesUnboundReason = (typeof UsesUnboundReason)[keyof typeof UsesUnboundReason];
303
+ /**
304
+ * 409 — a runtime read/write against a `uses` table whose
305
+ * `module_table_bindings` row is not `status='bound'` (Phase 4
306
+ * modules-platform-v2 workspace-table binding lifecycle).
307
+ *
308
+ * "Unbound" means the workspace-table slot is *declared* in the module's
309
+ * manifest `uses` block but not *connected* to a physical workspace
310
+ * table. It happens when install-time auto-match parked the slot (no
311
+ * candidate / ambiguous candidates / a write contract that never
312
+ * auto-binds), the bound table was later trashed, the manifest widened
313
+ * `ops` beyond consent, or an admin manually unbound it.
314
+ *
315
+ * A *recoverable* state, not a bug. Catch it and render a "connect a
316
+ * table" prompt — a workspace admin resolves it by binding a workspace
317
+ * table to the slot (`dashwise bind <uses_slug>` / the
318
+ * `PUT /api/installations/:id/bindings/:usesSlug` endpoint). Once bound,
319
+ * the same call succeeds with no code change.
320
+ *
321
+ * Convenience accessors read the backend's `context: { uses_slug, reason }`.
322
+ *
323
+ * @example
324
+ * ```ts
325
+ * import { UsesUnboundError } from '@dashai/sdk';
326
+ *
327
+ * try {
328
+ * const staff = await client.uses('employees').db<EmployeeRow>('employees').list();
329
+ * // …or the typed builder: await qb.uses.employees.execute();
330
+ * } catch (err) {
331
+ * if (err instanceof UsesUnboundError) {
332
+ * return <BindWorkspaceTable slot={err.usesSlug} reason={err.reason} />;
333
+ * }
334
+ * throw err;
335
+ * }
336
+ * ```
337
+ */
338
+ declare class UsesUnboundError extends DashwiseError {
339
+ constructor(message: string, context?: Record<string, unknown>, requestId?: string | null);
340
+ /**
341
+ * The manifest `uses[].tables[].slug` of the unbound slot (kebab-case,
342
+ * e.g. `employees`). Read from `context.uses_slug`; `undefined` if the
343
+ * backend omitted it.
344
+ */
345
+ get usesSlug(): string | undefined;
346
+ /**
347
+ * Why the slot is unbound — one of {@link UsesUnboundReason} (typed as
348
+ * `string` for forward-compat with reasons the backend may add). Read
349
+ * from `context.reason`; `undefined` if omitted.
350
+ */
351
+ get reason(): string | undefined;
352
+ }
353
+ /**
354
+ * 403 — a `uses`-plane operation that isn't in the binding's enforced
355
+ * operation set (the manifest's declared `ops` INTERSECT the admin's
356
+ * `consented_ops` at bind time). E.g. the manifest declares
357
+ * `ops: ['read','update']` but the admin consented only to `read` when
358
+ * binding, so an `update` is rejected.
359
+ *
360
+ * Fix: either narrow the call to a consented op, or widen the manifest
361
+ * `ops` + have an admin re-bind (which refreshes `consented_ops`).
362
+ *
363
+ * `err.op` / `err.usesSlug` read the backend's `context: { uses_slug, op }`.
364
+ */
365
+ declare class UsesOpNotAllowedError extends DashwiseError {
366
+ constructor(message: string, context?: Record<string, unknown>, requestId?: string | null);
367
+ /** The `uses` slot slug the rejected op targeted. Read from `context.uses_slug`. */
368
+ get usesSlug(): string | undefined;
369
+ /**
370
+ * The operation that was rejected — one of `create` / `read` /
371
+ * `update` / `delete`. Read from `context.op`; `undefined` if omitted.
372
+ */
373
+ get op(): string | undefined;
374
+ }
375
+ /**
376
+ * 409 — a field the `uses` binding's `field_map` points at no longer
377
+ * exists on the physical workspace table (schema drift: the table owner
378
+ * deleted or renamed the column after the bind). The backend best-effort
379
+ * parks the binding (reason `TABLE_DELETED`/field-drift) on detection.
380
+ *
381
+ * Recovery is the workspace admin's: re-bind the slot to a table that
382
+ * still has the field, or re-map the field (`dashwise bind <uses_slug>
383
+ * --map <usesField>=<physicalField>`).
384
+ *
385
+ * `err.field` / `err.usesSlug` read the backend's
386
+ * `context: { uses_slug, field }`.
387
+ */
388
+ declare class ContractFieldMissingError extends DashwiseError {
389
+ constructor(message: string, context?: Record<string, unknown>, requestId?: string | null);
390
+ /** The `uses` slot slug whose contract broke. Read from `context.uses_slug`. */
391
+ get usesSlug(): string | undefined;
392
+ /**
393
+ * The declared field slug (the `uses` side name) whose mapped physical
394
+ * field is gone. Read from `context.field`; `undefined` if omitted.
395
+ */
396
+ get field(): string | undefined;
397
+ }
398
+ /**
399
+ * 400 — `.join()` / `.leftJoin()` referenced a target the manifest
400
+ * can't resolve. Covers the three sub-cases above; inspect
401
+ * `err.code` to distinguish.
402
+ *
403
+ * Author-side fix in every case: either correct the slug, or pass
404
+ * an explicit `on` argument to bypass link-field inference.
405
+ */
406
+ declare class JoinError extends DashwiseError {
407
+ constructor(code: string, message: string, context?: Record<string, unknown>, requestId?: string | null);
408
+ }
409
+ interface BackendErrorEnvelope {
410
+ code?: string;
411
+ message?: string;
412
+ retriable?: boolean;
413
+ context?: Record<string, unknown>;
414
+ }
415
+ /**
416
+ * Build a typed `DashwiseError` from the backend's response envelope.
417
+ *
418
+ * The mapping picks the most specific subclass for codes we have a class
419
+ * for; everything else becomes a plain `DashwiseError` carrying the raw
420
+ * code. This keeps the type set small while still letting consumers
421
+ * branch on string codes when they want to.
422
+ *
423
+ * Phase 6 slice 6.2 (2026-05-19): accepts an optional `requestId` —
424
+ * the backend's `x-request-id` response header — and threads it onto
425
+ * every produced error so consumers can use it as a debugging trace
426
+ * anchor. Default `null` for backward compat; the transport always
427
+ * passes it through.
428
+ */
429
+ declare function fromBackendEnvelope(status: number, envelope: BackendErrorEnvelope | null, requestId?: string | null): DashwiseError;
430
+
431
+ export { ContractFieldMissingError as C, DepUnboundError as D, ForbiddenError as F, JoinError as J, NetworkError as N, OperationNotAllowedByProviderError as O, ProviderTableMissingError as P, RowNotFoundError as R, TimeoutError as T, UnauthenticatedError as U, ValidationError as V, DepUnboundReason as a, DependencyContractError as b, ContractViolationError as c, DashwiseError as d, DashwiseErrorCode as e, UsesOpNotAllowedError as f, UsesUnboundError as g, UsesUnboundReason as h, fromBackendEnvelope as i };