@fabrika/app 0.6.0 → 0.7.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 (80) hide show
  1. package/package.json +9 -9
  2. package/skill/SKILL.md +29 -21
  3. package/skill/references/app-setup.md +54 -36
  4. package/skill/references/dev.md +5 -5
  5. package/skill/references/endpoint.md +152 -25
  6. package/skill/references/errors.md +26 -23
  7. package/skill/references/files.md +187 -137
  8. package/skill/references/jobs.md +82 -35
  9. package/skill/references/public-intake.md +387 -236
  10. package/skill/references/spa.md +5 -5
  11. package/skill/references/start.md +2 -1
  12. package/skill/references/table-and-migration.md +24 -2
  13. package/skill/references/tests.md +8 -5
  14. package/skill/references/webhooks-links-connectors.md +65 -12
  15. package/src/bun.ts +3 -2
  16. package/src/client/contract.ts +184 -74
  17. package/src/client/index.ts +2 -1
  18. package/src/client/transport.ts +7 -2
  19. package/src/cloudflare.ts +2 -0
  20. package/src/contract/artifact-schema.ts +110 -15
  21. package/src/contract/build.ts +1184 -613
  22. package/src/contract/compile.ts +44 -10
  23. package/src/contract/connect.ts +71 -5
  24. package/src/contract/context.ts +132 -23
  25. package/src/contract/declaration.ts +78 -63
  26. package/src/contract/defaults.ts +64 -58
  27. package/src/contract/define.ts +76 -124
  28. package/src/contract/file.ts +78 -0
  29. package/src/contract/group.ts +244 -37
  30. package/src/contract/index.ts +18 -0
  31. package/src/contract/kit.ts +206 -126
  32. package/src/contract/platform.ts +8 -9
  33. package/src/contract/redirect.ts +49 -0
  34. package/src/contract/schema-from-shape.ts +7 -0
  35. package/src/contract/schema-shape.ts +10 -0
  36. package/src/contract/snapshot-source.ts +5 -0
  37. package/src/contract/token.ts +89 -0
  38. package/src/contract/webhook-binding.ts +26 -0
  39. package/src/contract/webhook-scheme.ts +32 -0
  40. package/src/files/handle.ts +22 -0
  41. package/src/files/kinds.ts +454 -0
  42. package/src/files/scan.ts +15 -9
  43. package/src/files/streams.ts +111 -0
  44. package/src/honeypot.ts +7 -0
  45. package/src/implement/anonymous.ts +18 -42
  46. package/src/implement/boot.ts +177 -159
  47. package/src/implement/bounded.ts +23 -0
  48. package/src/implement/browser-config.ts +4 -4
  49. package/src/implement/capability.ts +78 -2
  50. package/src/implement/{form-admission.ts → client-address.ts} +3 -38
  51. package/src/implement/dispatch.ts +810 -409
  52. package/src/implement/egress.ts +84 -0
  53. package/src/implement/faults.ts +11 -1
  54. package/src/implement/index.ts +3 -2
  55. package/src/implement/invocation.ts +135 -35
  56. package/src/implement/params.ts +88 -0
  57. package/src/implement/principal.ts +7 -0
  58. package/src/implement/public.ts +142 -0
  59. package/src/implement/tokens.ts +219 -0
  60. package/src/implement/types.ts +24 -3
  61. package/src/implement/urls.ts +78 -0
  62. package/src/implement/verifiers.ts +299 -0
  63. package/src/implement/webhook.ts +136 -55
  64. package/src/implement/workload.ts +16 -14
  65. package/src/index.ts +3 -0
  66. package/src/jobs/mail.ts +98 -10
  67. package/src/jobs/runner.ts +103 -71
  68. package/src/jobs/scrub.ts +4 -1
  69. package/src/jobs/types.ts +19 -2
  70. package/src/react/hooks.ts +2 -2
  71. package/src/react/provider.tsx +2 -2
  72. package/src/testing/dev.ts +2 -2
  73. package/src/testing/endpoint-access.ts +167 -128
  74. package/src/testing/kit.ts +79 -24
  75. package/src/testing/policy-isolation.ts +55 -29
  76. package/src/testing/proxy.ts +6 -2
  77. package/src/testing/sample-file.ts +30 -0
  78. package/src/client/files.ts +0 -135
  79. package/src/contract/file-schemas.ts +0 -25
  80. package/src/files/collections.ts +0 -848
@@ -2,15 +2,44 @@
2
2
  // handler with `.handle(fn)` beside it. `.handle` returns the declaration without the handler's type, so a contract
3
3
  // of many endpoints stays cheap to type-check, and an endpoint without `.handle` is not a group member.
4
4
 
5
- import type { RpcCaller } from '@fabrika/auth-core'
5
+ import type { EndpointCache, RpcCaller } from '@fabrika/auth-core'
6
6
  import type { AnyDbIndex, ReadOnlyUnscoped, Unavailable, UnscopedDeclaration, UnscopedMode } from '@fabrika/db/tables'
7
7
  import type { z } from 'zod/v4'
8
8
  import type { Snake } from '../from-row'
9
9
  import type { ExtraKeys, HandlerInput, IsAny } from '../implement/types'
10
10
  import type { AttachmentBrand } from './attachment'
11
- import type { CheckedAccess, Declared, EndpointContext, ExportContext, ImportOf, KitTypes, LinkContext, SqlMode } from './context'
11
+ import type {
12
+ CheckedAccess,
13
+ Declared,
14
+ EndpointContext,
15
+ ExportContext,
16
+ ImportOf,
17
+ KickContext,
18
+ KitTypes,
19
+ LinkContext,
20
+ PublicContext,
21
+ SqlMode,
22
+ TokensContext,
23
+ WebhooksContext,
24
+ } from './context'
12
25
  import type { ProcedureType } from './declaration'
13
- import type { AppAccess, InputOf, InputSchema, LinkAccess, MemberAccess, MutationAccess, NotLoose, Procedure, QueryAccess, Schema } from './define'
26
+ import type {
27
+ AppAccess,
28
+ CapabilitiesAccess,
29
+ CapabilityAccess,
30
+ ChallengeOption,
31
+ InputOf,
32
+ InputSchema,
33
+ LinkAccess,
34
+ MemberAccess,
35
+ MutationAccess,
36
+ NotLoose,
37
+ Procedure,
38
+ PublicAccess,
39
+ QueryAccess,
40
+ Schema,
41
+ } from './define'
42
+ import type { WithClaims } from './token'
14
43
 
15
44
  /** Fields a builder sets itself: a definition that carries one does not type-check. */
16
45
  type Owned<K extends string> = { readonly [P in K]?: never }
@@ -55,24 +84,105 @@ type OneLiteral<Is> = string extends Is ? Unavailable<"issues names one link mou
55
84
  : true extends IsUnion<Is> ? Unavailable<"issues names one link mount, as a literal: issues: 'shared'">
56
85
  : unknown
57
86
 
58
- /** `then` names one cron job, as a literal. */
59
- type OneJob<Th> = string extends Th ? Unavailable<"then names one cron job, as a literal: then: 'mailing'">
60
- : true extends IsUnion<Th> ? Unavailable<"then names one cron job, as a literal: then: 'mailing'">
87
+ /** A query writes nothing, so it has nothing to kick a job for and no binding to write. */
88
+ type NoKick = {
89
+ readonly kicks?: Unavailable<'a query kicks no job: declare kicks on a mutation'>
90
+ readonly binds?: Unavailable<'a query binds no webhook: declare binds on a mutation'>
91
+ }
92
+
93
+ /** `binds` names one webhook, as a literal. */
94
+ type OneWebhook<Bs> = string extends Bs ? Unavailable<"binds names one webhook, as a literal: binds: 'stripe'">
95
+ : true extends IsUnion<Bs> ? Unavailable<"binds names one webhook, as a literal: binds: 'stripe'">
61
96
  : unknown
62
97
 
63
- /** A mutation's `then`, inferred from its optional field and then required, like a declared field. */
64
- type KickField<Th> =
65
- & {
66
- /** The cron job this mutation kicks once its transaction committed; the schedule stays its recovery. */
67
- readonly then?: Th
68
- }
69
- & ([Th] extends [never] ? unknown : { readonly then: Th & NoInfer<OneJob<Th>> })
98
+ /** The webhook whose bindings a mutation writes (`ctx.webhooks`), inferred from its optional field and then required. */
99
+ type BindsField<Bs> =
100
+ & { readonly binds?: Bs }
101
+ & ([Bs] extends [never] ? unknown : { readonly binds: Bs & NoInfer<OneWebhook<Bs>> })
102
+
103
+ /** The jobs a mutation may kick (`ctx.kick`), inferred from its optional field and then required, as a literal list. */
104
+ export type KicksField<Ks> =
105
+ & { readonly kicks?: Ks }
106
+ & ([Ks] extends [never] ? unknown : { readonly kicks: Ks & NoInfer<LiteralList<Ks>> })
107
+
108
+ /** The token purposes a site signs (`ctx.tokens.sign`), inferred from its optional field and then required, as a literal list. */
109
+ export type SignsField<Sg, Purposes extends string> =
110
+ & { readonly signs?: Sg }
111
+ & ([Sg] extends [never] ? unknown : { readonly signs: Sg & NoInfer<KnownPurposes<Sg, Purposes>> })
112
+
113
+ /**
114
+ * The HTTPS origins a site's code calls (`fetch`): each an exact origin, no path or wildcard. A guard on the global
115
+ * `fetch` refuses any other while the site runs; a public procedure declares none.
116
+ */
117
+ export interface EgressField {
118
+ readonly egress?: readonly `https://${string}`[]
119
+ }
70
120
 
71
- /** A query writes nothing, so it has nothing to kick a job for. */
72
- type NoKick = { readonly then?: Unavailable<'a query kicks no job: declare then on a mutation'> }
121
+ /** Each purpose `signs` names is one of `defineApp`'s `tokens`. */
122
+ type KnownPurposes<Sg, Purposes extends string> = Sg extends readonly (infer P extends string)[]
123
+ ? [Exclude<P, Purposes>] extends [never] ? LiteralList<Sg>
124
+ : Unavailable<`signs names ${ListOf<Exclude<P, Purposes>>}, which defineApp's tokens do not declare`>
125
+ : unknown
73
126
 
74
127
  type IsUnion<T, All = T> = T extends unknown ? ([All] extends [T] ? false : true) : never
75
128
 
129
+ /** A bucket's calls per minute, or `null` to turn a default bucket off. */
130
+ type Bucket = number | null
131
+
132
+ /**
133
+ * How a procedure is admitted (`admission`), merged into its kind's default: a public mutation counts 10 calls per
134
+ * minute per client and 100 for the endpoint; every other procedure counts none unless it declares a bucket.
135
+ */
136
+ export type AdmissionOption<Acc> = [Acc] extends [PublicAccess] ? {
137
+ /** `'same-origin'` by default; `'listed'` the environment's listed origins; `'any'` every origin. */
138
+ readonly origins?: 'same-origin' | 'listed' | 'any'
139
+ readonly rate?: { readonly perClient?: Bucket; readonly perEndpoint?: Bucket; readonly bytesPerHour?: Bucket }
140
+ /** Verified on the server before the handler; the input carries the widget's token in `challengeToken`. */
141
+ readonly challenge?: ChallengeOption
142
+ }
143
+ : {
144
+ /** `'same-origin'` by default; `'listed'` the environment's listed origins, with a key only (ADR-0022). */
145
+ readonly origins?: 'same-origin' | 'listed'
146
+ readonly rate?: { readonly perCaller?: Bucket; readonly perEndpoint?: Bucket }
147
+ }
148
+
149
+ /** A procedure's bounds: its body in bytes (64 KiB by default, at most 1 MiB) and its handler's time (10 s, at most 60 s). */
150
+ export interface LimitsOption {
151
+ readonly maxBytes?: number
152
+ readonly timeoutMs?: number
153
+ }
154
+
155
+ /**
156
+ * A public procedure's workload actions, which its handler holds and nothing else; no other procedure declares them.
157
+ * Inferred from the optional field and then required, like a declared field.
158
+ */
159
+ export type PublicFields<Acc, Acts> = [Acc] extends [PublicAccess] ? {
160
+ readonly actions:
161
+ & Acts
162
+ & NoInfer<Acts extends readonly [] ? Unavailable<"a public procedure names what its handler holds: actions: ['<action>']"> : unknown>
163
+ }
164
+ : { readonly actions?: Unavailable<'only a public procedure declares actions: its handler runs as its own workload'> }
165
+
166
+ /** The handler context of a group's procedure: a public one runs as its own workload, every other as its caller. */
167
+ export type ProcedureContext<
168
+ K extends KitTypes,
169
+ Caller extends RpcCaller,
170
+ Kind extends 'query' | 'mutation',
171
+ Acc,
172
+ Acts extends readonly string[],
173
+ D extends Declared<SqlMode, unknown, readonly string[], string>,
174
+ Ks = never,
175
+ Bs = never,
176
+ Sg = never,
177
+ > =
178
+ & ([Acc] extends [PublicAccess] ? PublicContext<K, Kind, Acts[number]>
179
+ : EndpointContext<K, Caller, Kind, CheckedAccess<Acc>, D> & WebhooksContext<Bs>)
180
+ & KickContext<Ks>
181
+ & TokensContext<K, Sg>
182
+
183
+ /** A group without callers holds public procedures only; any other group may hold both. */
184
+ export type GroupAccess<Caller extends RpcCaller, Acc> = [Caller] extends [never] ? PublicAccess : Acc | PublicAccess
185
+
76
186
  /** An endpoint's declaration: its schemas, its access form and the reach it declares. */
77
187
  export type EndpointDef<I, O, Acc, S, U, Cn, Is, Ix extends AnyDbIndex> =
78
188
  & Owned<'~kind' | 'type'>
@@ -80,11 +190,23 @@ export type EndpointDef<I, O, Acc, S, U, Cn, Is, Ix extends AnyDbIndex> =
80
190
  readonly input?: I & NotLoose<I>
81
191
  readonly output: O & NotLoose<O>
82
192
  readonly access: Acc
83
- /** A page on one of the environment's listed origins may call it, with a key (ADR-0022). An RPC endpoint only. */
84
- readonly crossOrigin?: true
193
+ readonly admission?: AdmissionOption<Acc>
194
+ readonly limits?: LimitsOption
85
195
  }
86
196
  & DeclaredFields<S, U, Cn, Is, Ix>
87
197
 
198
+ /**
199
+ * A group procedure's HTTP shape, its `query` schema inferred: what its handler then reads as `query`. Only a public
200
+ * procedure has a path of its own.
201
+ */
202
+ type HttpField<Q, Acc> = { readonly http?: HttpOption<Q & NoInfer<NotLoose<Q>>> & OwnPathOption<Acc> }
203
+
204
+ /**
205
+ * `http.path`: a public procedure served at a literal path of its own instead of `<prefix>/<name>`, so a caller outside
206
+ * the application keeps its URL. It lies outside every mount's prefix and under no `/__fabrika`.
207
+ */
208
+ export type OwnPathOption<Acc> = [Acc] extends [PublicAccess] ? { readonly path?: `/${string}` } : unknown
209
+
88
210
  type Returned<F> = F extends (args: never) => infer R ? Awaited<R> : never
89
211
 
90
212
  /** The last member of a union, in the order the compiler holds it. */
@@ -120,8 +242,31 @@ export type HandlerReturn<F, O extends Schema> = [Returned<F>] extends [z.input<
120
242
  : [Returned<F>] extends [RowShaped<z.input<O>>] ? RowShaped<z.input<O>>
121
243
  : z.input<O>
122
244
 
123
- /** A kit endpoint's handler, returning `R`. */
124
- export type KitHandler<In, Ctx, R> = (args: { readonly input: In; readonly ctx: Ctx }) => R | Promise<R>
245
+ /** A kit endpoint's handler, returning `R`; `X` adds what its HTTP shape reads beside the input (`query`). */
246
+ export type KitHandler<In, Ctx, R, X = unknown> = (args: { readonly input: In; readonly ctx: Ctx } & X) => R | Promise<R>
247
+
248
+ /**
249
+ * What a handler reads beside its input: the URL's `query` of a POST that declares `http.query`, each signed token in it
250
+ * as the claims of its purpose.
251
+ */
252
+ export type QueryArgs<Q, T = Record<never, never>> = [Q] extends [never] ? unknown
253
+ : Q extends InputSchema ? { readonly query: WithClaims<z.output<Q>, T> }
254
+ : unknown
255
+
256
+ /**
257
+ * The wire of a procedure: `POST` with a JSON body by default; a query may be `GET`, its input then flat scalar URL
258
+ * parameters; a POST may read a flat `query` from the URL and take a native form's `urlencoded` body.
259
+ */
260
+ export interface HttpOption<Q> {
261
+ readonly method?: 'GET' | 'POST'
262
+ readonly query?: Q
263
+ readonly body?: 'json' | 'urlencoded'
264
+ /**
265
+ * A public GET query's successful answers may be reused: `{ maxAgeSeconds }`, or `'immutable'` (a year) when its
266
+ * input names an immutable value. Every other answer is `no-store`.
267
+ */
268
+ readonly cache?: EndpointCache
269
+ }
125
270
 
126
271
  /**
127
272
  * What `.handle` answers: the endpoint, or a message the group refuses at the endpoint's line — when the handler
@@ -143,10 +288,24 @@ export interface Endpoint<T extends ProcedureType, I extends InputSchema | null,
143
288
  readonly declared: D
144
289
  }
145
290
 
146
- /** An endpoint before `.handle`: a group refuses it. */
147
- export interface EndpointBuilder<T extends ProcedureType, I extends InputSchema | null, O extends Schema, Acc, D, Ctx> extends PendingEndpoint {
291
+ /**
292
+ * An endpoint before `.handle`: a group refuses it. `Tk` are the kit's token purposes: a signed token field of the input
293
+ * reaches the handler as the claims of its purpose.
294
+ */
295
+ export interface EndpointBuilder<
296
+ T extends ProcedureType,
297
+ I extends InputSchema | null,
298
+ O extends Schema,
299
+ Acc,
300
+ D,
301
+ Ctx,
302
+ X = unknown,
303
+ Tk = Record<never, never>,
304
+ > extends PendingEndpoint {
148
305
  /** The endpoint's handler, typed by its access form and declaration; it may return only the output's fields. */
149
- handle<const F extends KitHandler<HandlerInput<I, Acc>, Ctx, HandlerReturn<F, O>>>(handler: F): ExactReturn<F, O, Endpoint<T, I, O, Acc, D>>
306
+ handle<const F extends KitHandler<WithClaims<HandlerInput<I, Acc>, Tk>, Ctx, HandlerReturn<F, O>, X>>(
307
+ handler: F,
308
+ ): ExactReturn<F, O, Endpoint<T, I, O, Acc, D>>
150
309
  }
151
310
 
152
311
  /** What every endpoint builder has and no handled endpoint has. */
@@ -154,44 +313,71 @@ export interface PendingEndpoint {
154
313
  handle(handler: never): unknown
155
314
  }
156
315
 
157
- /** The builders of a group's callback: they know the group's callers, so a handler knows its principal. */
316
+ /**
317
+ * The builders of a group's callback: they know the group's callers, so a handler knows its principal. A group without
318
+ * callers (`Caller` is `never`) declares public procedures only.
319
+ */
158
320
  export interface GroupKit<K extends KitTypes, Caller extends RpcCaller> {
159
321
  query<
160
- const Acc extends QueryAccess<K['action'], K['dimension'], InputOf<I>>,
322
+ const Acc extends GroupAccess<Caller, QueryAccess<K['action'], K['dimension'], InputOf<I>>>,
161
323
  O extends Schema,
162
324
  I extends InputSchema | null = null,
163
325
  const S extends 'read' = never,
164
326
  const U extends UnscopedDeclaration<K['tables'], 'read'> = never,
165
327
  const Cn extends readonly ImportOf<K>[] = never,
166
328
  const Is extends string = never,
329
+ const Acts extends readonly K['action'][] = never,
330
+ Q extends InputSchema = never,
331
+ const Sg extends readonly string[] = never,
167
332
  >(
168
- def: EndpointDef<I, O, Acc, S, U, Cn, Is, K['index']> & NoKick,
333
+ def:
334
+ & EndpointDef<I, O, Acc, S, U, Cn, Is, K['index']>
335
+ & PublicFields<Acc, Acts>
336
+ & HttpField<Q, Acc>
337
+ & NoKick
338
+ & SignsField<Sg, keyof K['tokens'] & string>
339
+ & EgressField,
169
340
  ): EndpointBuilder<
170
341
  'query',
171
342
  I,
172
343
  O,
173
344
  Acc,
174
345
  Declared<S, U, Cn, Is>,
175
- EndpointContext<K, Caller, 'query', CheckedAccess<Acc>, Declared<S, U, Cn, Is>>
346
+ ProcedureContext<K, Caller, 'query', Acc, Acts, Declared<S, U, Cn, Is>, never, never, Sg>,
347
+ QueryArgs<Q, K['tokens']>,
348
+ K['tokens']
176
349
  >
177
350
  mutation<
178
- const Acc extends MutationAccess<K['action'], K['dimension'], K['creatable'], InputOf<I>>,
351
+ const Acc extends GroupAccess<Caller, MutationAccess<K['action'], K['dimension'], K['creatable'], InputOf<I>>>,
179
352
  O extends Schema,
180
353
  I extends InputSchema | null = null,
181
354
  const S extends SqlMode = never,
182
355
  const U extends UnscopedDeclaration<K['tables'], UnscopedMode> = never,
183
356
  const Cn extends readonly ImportOf<K>[] = never,
184
357
  const Is extends string = never,
185
- const Th extends string = never,
358
+ const Acts extends readonly K['action'][] = never,
359
+ Q extends InputSchema = never,
360
+ const Ks extends readonly string[] = never,
361
+ const Bs extends string = never,
362
+ const Sg extends readonly string[] = never,
186
363
  >(
187
- def: EndpointDef<I, O, Acc, S, U, Cn, Is, K['index']> & KickField<Th>,
364
+ def:
365
+ & EndpointDef<I, O, Acc, S, U, Cn, Is, K['index']>
366
+ & PublicFields<Acc, Acts>
367
+ & HttpField<Q, Acc>
368
+ & KicksField<Ks>
369
+ & BindsField<Bs>
370
+ & SignsField<Sg, keyof K['tokens'] & string>
371
+ & EgressField,
188
372
  ): EndpointBuilder<
189
373
  'mutation',
190
374
  I,
191
375
  O,
192
376
  Acc,
193
377
  Declared<S, U, Cn, Is>,
194
- EndpointContext<K, Caller, 'mutation', CheckedAccess<Acc>, Declared<S, U, Cn, Is>>
378
+ ProcedureContext<K, Caller, 'mutation', Acc, Acts, Declared<S, U, Cn, Is>, Ks, Bs, Sg>,
379
+ QueryArgs<Q, K['tokens']>,
380
+ K['tokens']
195
381
  >
196
382
  }
197
383
 
@@ -229,8 +415,8 @@ export type PendingIn<T, Path extends string> = typeof failedBuild extends keyof
229
415
  : string extends keyof T ? [IsPending<T[string & keyof T]>] extends [true] ? `${Path}* (its type admits an endpoint without a handler)` : never
230
416
  : { [K in keyof T]: [IsPending<T[K]>] extends [true] ? `${Path}${K & string}` : never }[keyof T]
231
417
 
232
- /** `app.group(…)`: endpoints for one set of callers, declared in any module and mounted by the contract. */
233
- export interface Group<C extends readonly [RpcCaller, ...RpcCaller[]], T extends GroupInput> {
418
+ /** `app.group(…)`: endpoints for one set of callers (none for a group of public procedures), mounted by the contract. */
419
+ export interface Group<C extends readonly RpcCaller[], T extends GroupInput> {
234
420
  readonly '~kind': 'group'
235
421
  readonly callers: C
236
422
  readonly endpoints: T
@@ -246,21 +432,42 @@ export interface LinkGroupKit<K extends KitTypes, LD extends string, G extends s
246
432
  const U extends UnscopedDeclaration<K['tables'], 'read'> = never,
247
433
  >(
248
434
  def: EndpointDef<I, O, Acc, S, U, never, never, K['index']> & NoKick,
249
- ): EndpointBuilder<'query', I, O, Acc, Declared<S, U, never, never>, LinkContext<K, 'query', LD, Acc['action'], Declared<S, U, never, never>>>
435
+ ): EndpointBuilder<
436
+ 'query',
437
+ I,
438
+ O,
439
+ Acc,
440
+ Declared<S, U, never, never>,
441
+ LinkContext<K, 'query', LD, Acc['action'], Declared<S, U, never, never>>,
442
+ unknown,
443
+ K['tokens']
444
+ >
250
445
  mutation<
251
446
  const Acc extends LinkAccess<G>,
252
447
  O extends Schema,
253
448
  I extends InputSchema | null = null,
254
449
  const S extends SqlMode = never,
255
450
  const U extends UnscopedDeclaration<K['tables'], UnscopedMode> = never,
256
- const Th extends string = never,
451
+ const Ks extends readonly string[] = never,
257
452
  >(
258
- def: EndpointDef<I, O, Acc, S, U, never, never, K['index']> & KickField<Th>,
259
- ): EndpointBuilder<'mutation', I, O, Acc, Declared<S, U, never, never>, LinkContext<K, 'mutation', LD, Acc['action'], Declared<S, U, never, never>>>
453
+ def: EndpointDef<I, O, Acc, S, U, never, never, K['index']> & KicksField<Ks>,
454
+ ): EndpointBuilder<
455
+ 'mutation',
456
+ I,
457
+ O,
458
+ Acc,
459
+ Declared<S, U, never, never>,
460
+ LinkContext<K, 'mutation', LD, Acc['action'], Declared<S, U, never, never>> & KickContext<Ks>,
461
+ unknown,
462
+ K['tokens']
463
+ >
260
464
  }
261
465
 
262
466
  /** An export procedure names its action and its scope; `{ member: true }` would give the consumer's key nothing to hold. */
263
- export type ExportAccess<A extends string, D extends string, In> = Exclude<QueryAccess<A, D, In>, MemberAccess | AppAccess<A>>
467
+ export type ExportAccess<A extends string, D extends string, In> = Exclude<
468
+ QueryAccess<A, D, In>,
469
+ MemberAccess | AppAccess<A> | CapabilitiesAccess<{ readonly [name: string]: CapabilityAccess<A, D, In> }>
470
+ >
264
471
 
265
472
  /** The builder of an export's callback: queries only, run read-only. */
266
473
  export interface ExportKit<K extends KitTypes> {
@@ -19,6 +19,7 @@ export {
19
19
  exportDescription,
20
20
  exportDescriptionSchema,
21
21
  incompatibleChanges,
22
+ incompatibleMountChanges,
22
23
  parseExportDescription,
23
24
  type SnapshotProcedure,
24
25
  } from './connect'
@@ -26,9 +27,26 @@ export type * from './context'
26
27
  export * from './declaration'
27
28
  export * from './defaults'
28
29
  export * from './define'
30
+ export { type ClientInput, file, type FileBrand, type FileMark, fileOf, type FileRef, type FileSchema, type FileStatus } from './file'
29
31
  export type * from './group'
30
32
  export * from './kit'
31
33
  export { schemaFromContract } from './platform'
32
34
  export { ContractError } from './problems'
35
+ export { type Redirect, redirect, type RedirectBrand, type RedirectMark, redirectOf, type RedirectOptions } from './redirect'
33
36
  export { SNAPSHOT_DIRECTORY, type SnapshotNames, snapshotNames, snapshotSource } from './snapshot-source'
37
+ export {
38
+ SIGNED_TOKEN_MAX_LENGTH,
39
+ signedToken,
40
+ type SignedTokenMark,
41
+ signedTokenOf,
42
+ type SignedTokenSchema,
43
+ token,
44
+ TOKEN_MAX_DAYS,
45
+ type TokenOptions,
46
+ type TokenPurpose,
47
+ type TokenPurposes,
48
+ type TokenSigning,
49
+ type WithClaims,
50
+ } from './token'
34
51
  export * from './vocabulary'
52
+ export { type WebhookBindings, WebhookSecret } from './webhook-binding'