@fleetless/contracts 6.0.0-next.3 → 6.1.0-next.1

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 (41) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/artifacts/openapi.json +636 -1
  3. package/artifacts/routes.json +101 -0
  4. package/artifacts/schema/addon-catalogue-entry.schema.json +75 -0
  5. package/artifacts/schema/addon-key.schema.json +11 -0
  6. package/artifacts/schema/admin-plan-change-request.schema.json +171 -0
  7. package/artifacts/schema/asset-plan-limit-details.schema.json +108 -0
  8. package/artifacts/schema/audit-actor.schema.json +2 -1
  9. package/artifacts/schema/audit-event.schema.json +2 -1
  10. package/artifacts/schema/audit-list-response.schema.json +2 -1
  11. package/artifacts/schema/org-addons.schema.json +39 -0
  12. package/artifacts/schema/org-lock.schema.json +23 -0
  13. package/artifacts/schema/org-locked-details.schema.json +17 -0
  14. package/artifacts/schema/org-plan-usage.schema.json +45 -0
  15. package/artifacts/schema/org-plan.schema.json +450 -0
  16. package/artifacts/schema/pending-plan-change.schema.json +112 -0
  17. package/artifacts/schema/plan-catalogue-entry.schema.json +226 -0
  18. package/artifacts/schema/plan-change-keep.schema.json +45 -0
  19. package/artifacts/schema/plan-change-reason.schema.json +10 -0
  20. package/artifacts/schema/plan-change-request.schema.json +71 -0
  21. package/artifacts/schema/plan-currency.schema.json +8 -0
  22. package/artifacts/schema/plan-features.schema.json +37 -0
  23. package/artifacts/schema/plan-id.schema.json +10 -0
  24. package/artifacts/schema/plan-limit-details.schema.json +87 -0
  25. package/artifacts/schema/plan-limits.schema.json +113 -0
  26. package/artifacts/schema/plan-overrides.schema.json +103 -0
  27. package/artifacts/schema/plan-prices.schema.json +33 -0
  28. package/artifacts/schema/plan-required-details.schema.json +42 -0
  29. package/dist/audit.d.ts +10 -0
  30. package/dist/audit.js +8 -1
  31. package/dist/errors.d.ts +138 -1
  32. package/dist/errors.js +94 -0
  33. package/dist/index.d.ts +6 -2
  34. package/dist/index.js +11 -1
  35. package/dist/plans.d.ts +525 -0
  36. package/dist/plans.js +442 -0
  37. package/dist/realtime.d.ts +2 -0
  38. package/dist/realtime.js +6 -0
  39. package/dist/routes.d.ts +5 -1
  40. package/dist/routes.js +58 -0
  41. package/package.json +1 -1
@@ -0,0 +1,525 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { z } from 'zod';
3
+ /**
4
+ * The plan catalogue.
5
+ *
6
+ * Four plans, cheapest first: `basic` (free), `plus`, `pro` and
7
+ * `enterprise` (sold by contract, never self-service — its limits and
8
+ * features are the catalogue's ceiling, not a priced row). Add-ons exist on
9
+ * `pro` only; see `ADDONS` and the `addons` feature.
10
+ */
11
+ export declare const planId: z.ZodEnum<{
12
+ basic: "basic";
13
+ plus: "plus";
14
+ pro: "pro";
15
+ enterprise: "enterprise";
16
+ }>;
17
+ export type PlanId = z.infer<typeof planId>;
18
+ /**
19
+ * Cheapest first. `requiredPlanFor` and `nextPlanRaising` both read "higher"
20
+ * and "lower" from this order, so a plan's position here — not its name — is
21
+ * what decides whether a change is an upgrade or a downgrade.
22
+ */
23
+ export declare const PLAN_ORDER: readonly PlanId[];
24
+ /**
25
+ * The limits a plan ties a number to. `history_days` and `audit_days` are
26
+ * not refused against — they size a retention window, not a quota that an
27
+ * action can exceed — but they share this vocabulary because they are read
28
+ * off the same catalogue row.
29
+ */
30
+ export declare const planLimitKey: z.ZodEnum<{
31
+ apps: "apps";
32
+ robots: "robots";
33
+ seats: "seats";
34
+ app_users: "app_users";
35
+ live_video_ms_per_month: "live_video_ms_per_month";
36
+ asset_bytes_per_robot: "asset_bytes_per_robot";
37
+ history_days: "history_days";
38
+ audit_days: "audit_days";
39
+ }>;
40
+ export type PlanLimitKey = z.infer<typeof planLimitKey>;
41
+ export declare const planLimits: z.ZodObject<{
42
+ seats: z.ZodNullable<z.ZodNumber>;
43
+ robots: z.ZodNullable<z.ZodNumber>;
44
+ apps: z.ZodNullable<z.ZodNumber>;
45
+ app_users: z.ZodNullable<z.ZodNumber>;
46
+ live_video_ms_per_month: z.ZodNullable<z.ZodNumber>;
47
+ asset_bytes_per_robot: z.ZodNullable<z.ZodNumber>;
48
+ history_days: z.ZodNullable<z.ZodNumber>;
49
+ audit_days: z.ZodNullable<z.ZodNumber>;
50
+ }, z.core.$strip>;
51
+ export type PlanLimits = z.infer<typeof planLimits>;
52
+ /**
53
+ * What a plan unlocks beyond a number: `app_mcp` (the app's MCP server),
54
+ * `two_factor` (a developer may turn it on), `require_two_factor` (an owner
55
+ * may force it org-wide), `app_oidc` (an app may federate sign-in to an
56
+ * external IdP), `hosted_logo` (a custom logo on the app's hosted pages),
57
+ * `audit_export` (the audit log's CSV export) and `addons` (whether add-ons
58
+ * may be bought at all — `pro` only).
59
+ */
60
+ export declare const planFeature: z.ZodEnum<{
61
+ require_two_factor: "require_two_factor";
62
+ two_factor: "two_factor";
63
+ app_mcp: "app_mcp";
64
+ app_oidc: "app_oidc";
65
+ hosted_logo: "hosted_logo";
66
+ audit_export: "audit_export";
67
+ addons: "addons";
68
+ }>;
69
+ export type PlanFeature = z.infer<typeof planFeature>;
70
+ export declare const planFeatures: z.ZodObject<{
71
+ require_two_factor: z.ZodBoolean;
72
+ two_factor: z.ZodBoolean;
73
+ app_mcp: z.ZodBoolean;
74
+ app_oidc: z.ZodBoolean;
75
+ hosted_logo: z.ZodBoolean;
76
+ audit_export: z.ZodBoolean;
77
+ addons: z.ZodBoolean;
78
+ }, z.core.$strip>;
79
+ export type PlanFeatures = z.infer<typeof planFeatures>;
80
+ export declare const planPrices: z.ZodObject<{
81
+ eur_month: z.ZodNumber;
82
+ usd_month: z.ZodNumber;
83
+ eur_year: z.ZodNumber;
84
+ usd_year: z.ZodNumber;
85
+ }, z.core.$strip>;
86
+ export type PlanPrices = z.infer<typeof planPrices>;
87
+ export declare const planSupport: z.ZodEnum<{
88
+ email: "email";
89
+ community: "community";
90
+ priority: "priority";
91
+ named_contact: "named_contact";
92
+ }>;
93
+ export type PlanSupport = z.infer<typeof planSupport>;
94
+ export declare const planCatalogueEntry: z.ZodObject<{
95
+ id: z.ZodEnum<{
96
+ basic: "basic";
97
+ plus: "plus";
98
+ pro: "pro";
99
+ enterprise: "enterprise";
100
+ }>;
101
+ name: z.ZodString;
102
+ limits: z.ZodObject<{
103
+ seats: z.ZodNullable<z.ZodNumber>;
104
+ robots: z.ZodNullable<z.ZodNumber>;
105
+ apps: z.ZodNullable<z.ZodNumber>;
106
+ app_users: z.ZodNullable<z.ZodNumber>;
107
+ live_video_ms_per_month: z.ZodNullable<z.ZodNumber>;
108
+ asset_bytes_per_robot: z.ZodNullable<z.ZodNumber>;
109
+ history_days: z.ZodNullable<z.ZodNumber>;
110
+ audit_days: z.ZodNullable<z.ZodNumber>;
111
+ }, z.core.$strip>;
112
+ features: z.ZodObject<{
113
+ require_two_factor: z.ZodBoolean;
114
+ two_factor: z.ZodBoolean;
115
+ app_mcp: z.ZodBoolean;
116
+ app_oidc: z.ZodBoolean;
117
+ hosted_logo: z.ZodBoolean;
118
+ audit_export: z.ZodBoolean;
119
+ addons: z.ZodBoolean;
120
+ }, z.core.$strip>;
121
+ prices: z.ZodNullable<z.ZodObject<{
122
+ eur_month: z.ZodNumber;
123
+ usd_month: z.ZodNumber;
124
+ eur_year: z.ZodNumber;
125
+ usd_year: z.ZodNumber;
126
+ }, z.core.$strip>>;
127
+ support: z.ZodEnum<{
128
+ email: "email";
129
+ community: "community";
130
+ priority: "priority";
131
+ named_contact: "named_contact";
132
+ }>;
133
+ }, z.core.$strip>;
134
+ export type PlanCatalogueEntry = z.infer<typeof planCatalogueEntry>;
135
+ /**
136
+ * What can be bought on top of a plan, each raising exactly one
137
+ * `planLimitKey` by `per_unit`. Exist on `pro` only: on any other plan an
138
+ * org's add-on counts are zero, and a plan change away from `pro` resets
139
+ * them to zero (the add-ons feature gate, `planFeature.addons`).
140
+ */
141
+ export declare const addonKey: z.ZodEnum<{
142
+ apps: "apps";
143
+ robots: "robots";
144
+ seats: "seats";
145
+ app_user_packs: "app_user_packs";
146
+ live_video_packs: "live_video_packs";
147
+ }>;
148
+ export type AddonKey = z.infer<typeof addonKey>;
149
+ export declare const addonCatalogueEntry: z.ZodObject<{
150
+ key: z.ZodEnum<{
151
+ apps: "apps";
152
+ robots: "robots";
153
+ seats: "seats";
154
+ app_user_packs: "app_user_packs";
155
+ live_video_packs: "live_video_packs";
156
+ }>;
157
+ raises: z.ZodEnum<{
158
+ apps: "apps";
159
+ robots: "robots";
160
+ seats: "seats";
161
+ app_users: "app_users";
162
+ live_video_ms_per_month: "live_video_ms_per_month";
163
+ asset_bytes_per_robot: "asset_bytes_per_robot";
164
+ history_days: "history_days";
165
+ audit_days: "audit_days";
166
+ }>;
167
+ per_unit: z.ZodNumber;
168
+ prices: z.ZodObject<{
169
+ eur_month: z.ZodNumber;
170
+ usd_month: z.ZodNumber;
171
+ eur_year: z.ZodNumber;
172
+ usd_year: z.ZodNumber;
173
+ }, z.core.$strip>;
174
+ }, z.core.$strip>;
175
+ export type AddonCatalogueEntry = z.infer<typeof addonCatalogueEntry>;
176
+ /**
177
+ * **No floating-point money, anywhere.** `eurCents * 1.15` would introduce
178
+ * the fraction of a cent that floating point cannot hold exactly, so the
179
+ * conversion is integer arithmetic throughout: scale by 115, add 9_999 to
180
+ * round the result up to the next whole 10_000 (i.e. the next whole dollar)
181
+ * and only then divide back down. Rounds *up*, never to nearest: a plan that
182
+ * reads cheaper in dollars than its true euro equivalent is the error this
183
+ * guards against, not the one it risks.
184
+ */
185
+ export declare function usdCentsFromEurCents(eurCents: number): number;
186
+ /** Yearly is twelve months at 15% off, rounded to the nearest cent. */
187
+ export declare function yearlyEurCents(monthEurCents: number): number;
188
+ /**
189
+ * The catalogue writes every price through this one function, from the
190
+ * monthly EUR cents alone — never as the other three numbers as literals —
191
+ * so the USD and yearly rules can only ever be applied once, here.
192
+ */
193
+ export declare function pricesFromEurMonth(eurMonthCents: number): PlanPrices;
194
+ /**
195
+ * The catalogue, exactly as the decision table (2026-09-30) states it.
196
+ * Live video is in milliseconds, asset storage in decimal bytes per robot;
197
+ * Enterprise's limits and features are `null` / `true` throughout because
198
+ * they are set by contract, not read off this table.
199
+ */
200
+ export declare const PLANS: Readonly<Record<PlanId, PlanCatalogueEntry>>;
201
+ /**
202
+ * The add-on catalogue. Every price goes through `pricesFromEurMonth`, same
203
+ * discipline as `PLANS`.
204
+ */
205
+ export declare const ADDONS: Readonly<Record<AddonKey, AddonCatalogueEntry>>;
206
+ /** The cheapest plan that has the feature. */
207
+ export declare function requiredPlanFor(feature: PlanFeature): PlanId;
208
+ /**
209
+ * The cheapest plan above `plan` whose catalogue limit for `key` is higher
210
+ * than `plan`'s own (`null` counts as higher, since it means unlimited);
211
+ * `null` when no plan above it raises the limit any further.
212
+ */
213
+ export declare function nextPlanRaising(plan: PlanId, key: PlanLimitKey): PlanId | null;
214
+ /** What an org is billed in. The catalogue's prices are fixed in both; this picks which one an invoice reads in. */
215
+ export declare const planCurrency: z.ZodEnum<{
216
+ eur: "eur";
217
+ usd: "usd";
218
+ }>;
219
+ export type PlanCurrency = z.infer<typeof planCurrency>;
220
+ /**
221
+ * How many units of each add-on an org has bought. Meaningful on `pro` only
222
+ * — see `planFeature.addons` — and zero on every other plan: a plan change
223
+ * away from `pro` resets every count here to zero rather than leaving them
224
+ * stored and merely unread.
225
+ */
226
+ export declare const orgAddons: z.ZodObject<{
227
+ seats: z.ZodNumber;
228
+ robots: z.ZodNumber;
229
+ apps: z.ZodNumber;
230
+ app_user_packs: z.ZodNumber;
231
+ live_video_packs: z.ZodNumber;
232
+ }, z.core.$strip>;
233
+ export type OrgAddons = z.infer<typeof orgAddons>;
234
+ /**
235
+ * What the org is using right now, counted the way each limit refuses
236
+ * against: `seats` is developers, owners included, plus pending team
237
+ * invitations; `app_users` is app users of every app plus pending app-user
238
+ * invitations; `live_video_ms_this_month` is this UTC calendar month's
239
+ * app-attributed live video only — a console session never counts and is
240
+ * never ended for it; `asset_bytes` is the sum of every robot's stored
241
+ * assets across the whole org. Read fresh on every call, the same discipline
242
+ * `GET /api/org/quotas` already keeps, so a number here is never one call
243
+ * behind the limit it is compared against.
244
+ */
245
+ export declare const orgPlanUsage: z.ZodObject<{
246
+ seats: z.ZodNumber;
247
+ robots: z.ZodNumber;
248
+ apps: z.ZodNumber;
249
+ app_users: z.ZodNumber;
250
+ live_video_ms_this_month: z.ZodNumber;
251
+ asset_bytes: z.ZodNumber;
252
+ }, z.core.$strip>;
253
+ export type OrgPlanUsage = z.infer<typeof orgPlanUsage>;
254
+ /**
255
+ * What a downward plan change keeps, by id, when the target plan cannot hold
256
+ * everything the org has today. `owners` is deliberately not a field: an
257
+ * owner is never a candidate for deletion and always stays, so a chooser
258
+ * cannot even name one here — but an owner still counts against the target
259
+ * plan's `seats`, and if the owners alone already exceed it the change is
260
+ * refused `409 plan_limit` naming `seats`, before anything else about the
261
+ * choice is even considered. `.strict()` so an extra key — `owners` most of
262
+ * all — is refused at the door rather than silently ignored.
263
+ */
264
+ export declare const planChangeKeep: z.ZodObject<{
265
+ robots: z.ZodArray<z.ZodUUID>;
266
+ apps: z.ZodArray<z.ZodUUID>;
267
+ app_users: z.ZodArray<z.ZodUUID>;
268
+ developers: z.ZodArray<z.ZodUUID>;
269
+ }, z.core.$strict>;
270
+ export type PlanChangeKeep = z.infer<typeof planChangeKeep>;
271
+ /**
272
+ * Why a change is pending. `downgrade` and `cancel` (to Basic) are a
273
+ * developer's own choice — `PUT /api/org/plan/change` only ever moves an org
274
+ * down; an upgrade or an add-on needs payment this route does not collect,
275
+ * and today goes through a Feedback request that Fleetless applies through
276
+ * the admin route. `migration` is a plan the platform is moving every org on
277
+ * the beta through; `lock` is a change the platform queued because the org
278
+ * is locked (see `orgLock`) and must land on Basic.
279
+ */
280
+ export declare const planChangeReason: z.ZodEnum<{
281
+ cancel: "cancel";
282
+ downgrade: "downgrade";
283
+ migration: "migration";
284
+ lock: "lock";
285
+ }>;
286
+ export type PlanChangeReason = z.infer<typeof planChangeReason>;
287
+ /**
288
+ * A downward plan change the org has chosen, or been queued for by the
289
+ * platform, not yet in effect. `effective_at` is normally
290
+ * `orgPlan.period_ends_at`, so the org keeps full use of what it has until
291
+ * the billing period actually turns over — except a choice made while the
292
+ * org was locked, which takes effect at once, and a `migration`, which takes
293
+ * effect at the platform's switch date instead; it is `null` only while that
294
+ * date is not yet set. `keep` is `null` when the org's usage already fits
295
+ * the target plan outright and nothing is deleted; otherwise it is exactly
296
+ * what the confirmation counted — anything created while the choice is still
297
+ * pending is checked against the target plan too and, passing, is folded
298
+ * into `keep`, so what lands at `effective_at` is never a surprise. A later
299
+ * `PUT /api/org/plan/change` replaces a still-pending choice outright;
300
+ * `DELETE` withdraws it and leaves the org on its current plan.
301
+ * `history_days_after` is what the confirmation announces to whoever chose
302
+ * it, so the warning they read before confirming is the same number that
303
+ * lands.
304
+ */
305
+ export declare const pendingPlanChange: z.ZodObject<{
306
+ target_plan: z.ZodEnum<{
307
+ basic: "basic";
308
+ plus: "plus";
309
+ pro: "pro";
310
+ enterprise: "enterprise";
311
+ }>;
312
+ reason: z.ZodEnum<{
313
+ cancel: "cancel";
314
+ downgrade: "downgrade";
315
+ migration: "migration";
316
+ lock: "lock";
317
+ }>;
318
+ effective_at: z.ZodNullable<z.ZodISODateTime>;
319
+ keep: z.ZodNullable<z.ZodObject<{
320
+ robots: z.ZodArray<z.ZodUUID>;
321
+ apps: z.ZodArray<z.ZodUUID>;
322
+ app_users: z.ZodArray<z.ZodUUID>;
323
+ developers: z.ZodArray<z.ZodUUID>;
324
+ }, z.core.$strict>>;
325
+ history_days_after: z.ZodNumber;
326
+ chosen_by: z.ZodUUID;
327
+ chosen_at: z.ZodISODateTime;
328
+ }, z.core.$strip>;
329
+ export type PendingPlanChange = z.infer<typeof pendingPlanChange>;
330
+ /**
331
+ * An org restricted, while locked, to moving straight to Basic — narrower
332
+ * still than the already-downward-only `PUT /api/org/plan/change`. `payment`
333
+ * is a failed charge; `migration` is the platform's own move off the beta.
334
+ * Either way the only plan a developer may choose while locked is Basic —
335
+ * see `target_state_conflict` with rule `locked_basic_only` on
336
+ * `PUT /api/org/plan/change`; a choice made while locked takes effect at
337
+ * once rather than waiting for the billing period to turn over.
338
+ */
339
+ export declare const orgLock: z.ZodObject<{
340
+ reason: z.ZodEnum<{
341
+ migration: "migration";
342
+ payment: "payment";
343
+ }>;
344
+ since: z.ZodISODateTime;
345
+ }, z.core.$strip>;
346
+ export type OrgLock = z.infer<typeof orgLock>;
347
+ /**
348
+ * **The one read everything about an org's plan comes from**: the console's
349
+ * Plan & billing page, its usage and limit gauges, every upgrade prompt and
350
+ * every gate a feature check renders. `limits` is the *effective* ceiling —
351
+ * the catalogue row plus `addons`, or an operator's `overrides` in place of
352
+ * either — so a consumer never has to recompute it from the catalogue and
353
+ * the add-on counts itself. `switch` is set only for an organization still
354
+ * on the beta and carries the date its plan changes on its own, and whether
355
+ * it still has to choose one.
356
+ */
357
+ export declare const orgPlan: z.ZodObject<{
358
+ plan: z.ZodEnum<{
359
+ basic: "basic";
360
+ plus: "plus";
361
+ pro: "pro";
362
+ enterprise: "enterprise";
363
+ }>;
364
+ currency: z.ZodEnum<{
365
+ eur: "eur";
366
+ usd: "usd";
367
+ }>;
368
+ period_ends_at: z.ZodISODateTime;
369
+ addons: z.ZodObject<{
370
+ seats: z.ZodNumber;
371
+ robots: z.ZodNumber;
372
+ apps: z.ZodNumber;
373
+ app_user_packs: z.ZodNumber;
374
+ live_video_packs: z.ZodNumber;
375
+ }, z.core.$strip>;
376
+ limits: z.ZodObject<{
377
+ seats: z.ZodNullable<z.ZodNumber>;
378
+ robots: z.ZodNullable<z.ZodNumber>;
379
+ apps: z.ZodNullable<z.ZodNumber>;
380
+ app_users: z.ZodNullable<z.ZodNumber>;
381
+ live_video_ms_per_month: z.ZodNullable<z.ZodNumber>;
382
+ asset_bytes_per_robot: z.ZodNullable<z.ZodNumber>;
383
+ history_days: z.ZodNullable<z.ZodNumber>;
384
+ audit_days: z.ZodNullable<z.ZodNumber>;
385
+ }, z.core.$strip>;
386
+ features: z.ZodObject<{
387
+ require_two_factor: z.ZodBoolean;
388
+ two_factor: z.ZodBoolean;
389
+ app_mcp: z.ZodBoolean;
390
+ app_oidc: z.ZodBoolean;
391
+ hosted_logo: z.ZodBoolean;
392
+ audit_export: z.ZodBoolean;
393
+ addons: z.ZodBoolean;
394
+ }, z.core.$strip>;
395
+ usage: z.ZodObject<{
396
+ seats: z.ZodNumber;
397
+ robots: z.ZodNumber;
398
+ apps: z.ZodNumber;
399
+ app_users: z.ZodNumber;
400
+ live_video_ms_this_month: z.ZodNumber;
401
+ asset_bytes: z.ZodNumber;
402
+ }, z.core.$strip>;
403
+ pending_change: z.ZodNullable<z.ZodObject<{
404
+ target_plan: z.ZodEnum<{
405
+ basic: "basic";
406
+ plus: "plus";
407
+ pro: "pro";
408
+ enterprise: "enterprise";
409
+ }>;
410
+ reason: z.ZodEnum<{
411
+ cancel: "cancel";
412
+ downgrade: "downgrade";
413
+ migration: "migration";
414
+ lock: "lock";
415
+ }>;
416
+ effective_at: z.ZodNullable<z.ZodISODateTime>;
417
+ keep: z.ZodNullable<z.ZodObject<{
418
+ robots: z.ZodArray<z.ZodUUID>;
419
+ apps: z.ZodArray<z.ZodUUID>;
420
+ app_users: z.ZodArray<z.ZodUUID>;
421
+ developers: z.ZodArray<z.ZodUUID>;
422
+ }, z.core.$strict>>;
423
+ history_days_after: z.ZodNumber;
424
+ chosen_by: z.ZodUUID;
425
+ chosen_at: z.ZodISODateTime;
426
+ }, z.core.$strip>>;
427
+ lock: z.ZodNullable<z.ZodObject<{
428
+ reason: z.ZodEnum<{
429
+ migration: "migration";
430
+ payment: "payment";
431
+ }>;
432
+ since: z.ZodISODateTime;
433
+ }, z.core.$strip>>;
434
+ switch: z.ZodNullable<z.ZodObject<{
435
+ at: z.ZodNullable<z.ZodISODateTime>;
436
+ needs_choice: z.ZodBoolean;
437
+ }, z.core.$strip>>;
438
+ }, z.core.$strip>;
439
+ export type OrgPlan = z.infer<typeof orgPlan>;
440
+ /**
441
+ * What a developer may ask for on `PUT /api/org/plan/change` — **a downward
442
+ * move only**: a lower plan, or Basic as a cancellation. An upgrade or an
443
+ * add-on needs payment this route does not collect, and is not reachable
444
+ * through it at all today; it goes through a Feedback request that Fleetless
445
+ * applies through the admin route instead. `.strict()` for the same reason
446
+ * `planChangeKeep` is: a caller cannot send a field this shape does not
447
+ * name, `keep` included, and an owner cannot be smuggled into it through a
448
+ * typo that `.strict()` would otherwise swallow in silence.
449
+ */
450
+ export declare const planChangeRequest: z.ZodObject<{
451
+ target_plan: z.ZodEnum<{
452
+ basic: "basic";
453
+ plus: "plus";
454
+ pro: "pro";
455
+ enterprise: "enterprise";
456
+ }>;
457
+ keep: z.ZodNullable<z.ZodObject<{
458
+ robots: z.ZodArray<z.ZodUUID>;
459
+ apps: z.ZodArray<z.ZodUUID>;
460
+ app_users: z.ZodArray<z.ZodUUID>;
461
+ developers: z.ZodArray<z.ZodUUID>;
462
+ }, z.core.$strict>>;
463
+ }, z.core.$strict>;
464
+ export type PlanChangeRequest = z.infer<typeof planChangeRequest>;
465
+ /**
466
+ * An operator's per-org replacement for one or more catalogue limits —
467
+ * Enterprise's contracted numbers, most of all, which exist nowhere else.
468
+ * Every key is optional, so an operator sets only what differs from the
469
+ * plan; a key present with `null` clears an earlier override back to the
470
+ * plan's own number, which is why every value is nullable as well as
471
+ * optional — omitted and `null` are two different instructions.
472
+ */
473
+ export declare const planOverrides: z.ZodObject<{
474
+ apps: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
475
+ robots: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
476
+ seats: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
477
+ app_users: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
478
+ live_video_ms_per_month: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
479
+ asset_bytes_per_robot: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
480
+ history_days: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
481
+ audit_days: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
482
+ }, z.core.$strict>;
483
+ export type PlanOverrides = z.infer<typeof planOverrides>;
484
+ /**
485
+ * What the operator sends on `PATCH /api/admin/orgs/:id/plan`. Every field
486
+ * is optional because this one route carries every shape of change an
487
+ * operator makes to an org's plan — switching it, adding or removing
488
+ * add-ons, overriding a limit, changing the billing currency, or moving the
489
+ * period boundary — and a request that touched all of them at once would be
490
+ * no easier to audit than four small ones in its place. `addons` is a
491
+ * partial `orgAddons`: only the counts named change, the rest are left as
492
+ * they are. `overrides` follows `planOverrides`: a key present with `null`
493
+ * clears that override.
494
+ */
495
+ export declare const adminPlanChangeRequest: z.ZodObject<{
496
+ plan: z.ZodEnum<{
497
+ basic: "basic";
498
+ plus: "plus";
499
+ pro: "pro";
500
+ enterprise: "enterprise";
501
+ }>;
502
+ addons: z.ZodOptional<z.ZodObject<{
503
+ seats: z.ZodOptional<z.ZodNumber>;
504
+ robots: z.ZodOptional<z.ZodNumber>;
505
+ apps: z.ZodOptional<z.ZodNumber>;
506
+ app_user_packs: z.ZodOptional<z.ZodNumber>;
507
+ live_video_packs: z.ZodOptional<z.ZodNumber>;
508
+ }, z.core.$strict>>;
509
+ overrides: z.ZodOptional<z.ZodObject<{
510
+ apps: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
511
+ robots: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
512
+ seats: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
513
+ app_users: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
514
+ live_video_ms_per_month: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
515
+ asset_bytes_per_robot: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
516
+ history_days: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
517
+ audit_days: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
518
+ }, z.core.$strict>>;
519
+ currency: z.ZodOptional<z.ZodEnum<{
520
+ eur: "eur";
521
+ usd: "usd";
522
+ }>>;
523
+ period_ends_at: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
524
+ }, z.core.$strict>;
525
+ export type AdminPlanChangeRequest = z.infer<typeof adminPlanChangeRequest>;