@fleetless/contracts 5.3.0-next.1 → 6.0.0-next.2

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 (89) hide show
  1. package/CHANGELOG.md +108 -33
  2. package/artifacts/openapi.json +2053 -784
  3. package/artifacts/routes.json +1680 -323
  4. package/artifacts/schema/accept-team-invite-request.schema.json +13 -7
  5. package/artifacts/schema/app-auth-config.schema.json +108 -4
  6. package/artifacts/schema/app-hosted-pages.schema.json +33 -0
  7. package/artifacts/schema/app-invitation.schema.json +5 -12
  8. package/artifacts/schema/app-mail-template-list-response.schema.json +4 -3
  9. package/artifacts/schema/app-mail-template.schema.json +3 -2
  10. package/artifacts/schema/app-sign-in-methods.schema.json +19 -0
  11. package/artifacts/schema/app-user-list-response.schema.json +36 -0
  12. package/artifacts/schema/app-user.schema.json +36 -0
  13. package/artifacts/schema/audit-query.schema.json +0 -6
  14. package/artifacts/schema/auth-me-response.schema.json +27 -0
  15. package/artifacts/schema/auth-ok.schema.json +13 -1
  16. package/artifacts/schema/client-accept-invitation-request.schema.json +3 -4
  17. package/artifacts/schema/client-identity.schema.json +13 -1
  18. package/artifacts/schema/client-login-code-request.schema.json +24 -0
  19. package/artifacts/schema/client-login-code-verify-request.schema.json +30 -0
  20. package/artifacts/schema/client-provider-list-response.schema.json +22 -2
  21. package/artifacts/schema/client-register-request.schema.json +3 -4
  22. package/artifacts/schema/client-sign-in-result.schema.json +55 -0
  23. package/artifacts/schema/client-two-factor-disable-request.schema.json +15 -0
  24. package/artifacts/schema/client-two-factor-setup-confirm-request.schema.json +20 -0
  25. package/artifacts/schema/client-two-factor-setup-confirm-response.schema.json +49 -0
  26. package/artifacts/schema/client-two-factor-setup-request.schema.json +12 -0
  27. package/artifacts/schema/client-two-factor-verify-request.schema.json +25 -0
  28. package/artifacts/schema/create-app-invitation-request.schema.json +1 -1
  29. package/artifacts/schema/create-passkey-request.schema.json +25 -0
  30. package/artifacts/schema/create-passkey-response.schema.json +84 -0
  31. package/artifacts/schema/developer-passkey.schema.json +56 -0
  32. package/artifacts/schema/developer-two-factor.schema.json +105 -0
  33. package/artifacts/schema/fleetless-user-list-response.schema.json +22 -0
  34. package/artifacts/schema/fleetless-user.schema.json +22 -0
  35. package/artifacts/schema/invalid-code-details.schema.json +16 -0
  36. package/artifacts/schema/job-actor.schema.json +1 -15
  37. package/artifacts/schema/job-run-list-response.schema.json +1 -15
  38. package/artifacts/schema/job-run.schema.json +1 -15
  39. package/artifacts/schema/org.schema.json +5 -0
  40. package/artifacts/schema/patch-org-request.schema.json +5 -3
  41. package/artifacts/schema/patch-org-response.schema.json +5 -0
  42. package/artifacts/schema/put-app-auth-look-request.schema.json +22 -0
  43. package/artifacts/schema/put-app-auth-mcp-request.schema.json +1 -14
  44. package/artifacts/schema/put-app-auth-sign-in-request.schema.json +39 -0
  45. package/artifacts/schema/put-app-auth-urls-request.schema.json +31 -4
  46. package/artifacts/schema/recovery-codes-response.schema.json +20 -0
  47. package/artifacts/schema/{role-rename-request.schema.json → rename-passkey-request.schema.json} +2 -2
  48. package/artifacts/schema/role-list-response.schema.json +1 -1
  49. package/artifacts/schema/role.schema.json +1 -1
  50. package/artifacts/schema/totp-confirm-request.schema.json +15 -0
  51. package/artifacts/schema/totp-confirm-response.schema.json +27 -0
  52. package/artifacts/schema/two-factor-challenge.schema.json +24 -0
  53. package/artifacts/schema/two-factor-setup-response.schema.json +21 -0
  54. package/artifacts/schema/webauthn-options-response.schema.json +18 -0
  55. package/dist/app-users.d.ts +154 -35
  56. package/dist/app-users.js +177 -46
  57. package/dist/apps.d.ts +2 -38
  58. package/dist/apps.js +3 -46
  59. package/dist/audit.d.ts +0 -1
  60. package/dist/audit.js +0 -13
  61. package/dist/client-auth.d.ts +133 -24
  62. package/dist/client-auth.js +139 -28
  63. package/dist/config.d.ts +2 -2
  64. package/dist/errors.d.ts +10 -1
  65. package/dist/errors.js +37 -38
  66. package/dist/identity.d.ts +175 -128
  67. package/dist/identity.js +192 -106
  68. package/dist/index.d.ts +11 -13
  69. package/dist/index.js +12 -10
  70. package/dist/jobs.d.ts +0 -3
  71. package/dist/jobs.js +0 -16
  72. package/dist/protocol.d.ts +1 -1
  73. package/dist/realtime.d.ts +1 -0
  74. package/dist/rest.d.ts +2 -2
  75. package/dist/rest.js +17 -28
  76. package/dist/routes.d.ts +26 -0
  77. package/dist/routes.js +528 -234
  78. package/package.json +1 -1
  79. package/artifacts/schema/developer-login-request.schema.json +0 -19
  80. package/artifacts/schema/feedback-request.schema.json +0 -34
  81. package/artifacts/schema/feedback-response.schema.json +0 -27
  82. package/artifacts/schema/password-reset-confirm.schema.json +0 -19
  83. package/artifacts/schema/password-reset-request.schema.json +0 -14
  84. package/artifacts/schema/role-delete-query.schema.json +0 -13
  85. package/artifacts/schema/role-in-use-details.schema.json +0 -28
  86. package/artifacts/schema/sign-up-request.schema.json +0 -26
  87. package/artifacts/schema/sign-up-response.schema.json +0 -127
  88. package/dist/feedback.d.ts +0 -42
  89. package/dist/feedback.js +0 -35
@@ -14,19 +14,22 @@ import { z } from 'zod';
14
14
  * So there are now **two identity spaces and nothing joins them**:
15
15
  *
16
16
  * - *Fleetless users* (`identity.ts`) — the org's team. Email globally unique,
17
- * tier `owner | developer`, Fleetless password, console access.
17
+ * tier `owner | developer`, sign-in by emailed code or passkey, console
18
+ * access.
18
19
  * - *app users* (this file) — one app each. Email unique **per app**,
19
20
  * case-insensitively. The same address may exist in several apps of one org
20
21
  * as unrelated accounts, and a Fleetless user who wants to use an app
21
22
  * registers or is invited like anybody else.
22
23
  *
23
- * **Fleetless shows an app user no page**. The developer's own UI owns
24
- * every screen and calls the JSON client-auth API (`client-auth.ts`). The one
25
- * Fleetless-rendered surface an app user can reach is the problem page for an
26
- * OIDC callback whose state no longer resolves to a redirect URI — every other
27
- * error is redirected to the app to render. That is why the four URLs on
28
- * `appAuthConfig` exist: Fleetless mails a link, and the link points into the
29
- * app.
24
+ * **The developer's own UI owns every screen it wants to own**, and calls the
25
+ * JSON client-auth API (`client-auth.ts`). Fleetless mails a link, and the
26
+ * link points into the app — at the four URLs on `appAuthConfig`. **A URL the
27
+ * app leaves unset falls back to a Fleetless-hosted page** on the auth portal
28
+ * (`hosted_pages`), carrying the app's name, its optional logo and accent
29
+ * colour, so an app works from its first minute: with no web UI of its own,
30
+ * and while its pages point nowhere yet. A set URL always wins. The hosted
31
+ * pages cover mailed links and MCP sign-in only; they are not a hosted login
32
+ * for the app's own web UI.
30
33
  */
31
34
  /** App-user display names share the Fleetless-user bound, so a rename cannot be legal in one space and refused in the other. */
32
35
  export declare const APP_USER_DISPLAY_NAME_MAX = 120;
@@ -84,6 +87,11 @@ export declare const appUser: z.ZodObject<{
84
87
  has_password: z.ZodBoolean;
85
88
  providers: z.ZodArray<z.ZodString>;
86
89
  last_login_at: z.ZodNullable<z.ZodISODateTime>;
90
+ two_factor: z.ZodObject<{
91
+ enabled: z.ZodBoolean;
92
+ enabled_at: z.ZodNullable<z.ZodISODateTime>;
93
+ recovery_codes_left: z.ZodNumber;
94
+ }, z.core.$strip>;
87
95
  created_at: z.ZodISODateTime;
88
96
  }, z.core.$strip>;
89
97
  export type AppUser = z.infer<typeof appUser>;
@@ -103,6 +111,11 @@ export declare const appUserListResponse: z.ZodObject<{
103
111
  has_password: z.ZodBoolean;
104
112
  providers: z.ZodArray<z.ZodString>;
105
113
  last_login_at: z.ZodNullable<z.ZodISODateTime>;
114
+ two_factor: z.ZodObject<{
115
+ enabled: z.ZodBoolean;
116
+ enabled_at: z.ZodNullable<z.ZodISODateTime>;
117
+ recovery_codes_left: z.ZodNumber;
118
+ }, z.core.$strip>;
106
119
  created_at: z.ZodISODateTime;
107
120
  }, z.core.$strip>>;
108
121
  }, z.core.$strip>;
@@ -162,12 +175,10 @@ export type CreateAppInvitationRequest = z.infer<typeof createAppInvitationReque
162
175
  /**
163
176
  * The invitation as issued.
164
177
  *
165
- * **`accept_url` is nullable, and that is a policy rather than a convenience.**
166
- * The link points into the developer's app, at their configured `invite_url`.
167
- * An app that has configured none has nowhere for it to point, so there is no
168
- * link to hand back — `null` says that outright, where an absent key would be
169
- * indistinguishable from a mapper that dropped the field and a fabricated
170
- * Fleetless-hosted URL would name a page this product does not serve.
178
+ * The link points into the developer's app, at their configured `invite_url`,
179
+ * or at the Fleetless-hosted invitation page (`appAuthConfig.hosted_pages`)
180
+ * when the app has configured none — so there is always a link, and
181
+ * `accept_url` is never `null`.
171
182
  */
172
183
  export declare const appInvitation: z.ZodObject<{
173
184
  id: z.ZodUUID;
@@ -175,7 +186,7 @@ export declare const appInvitation: z.ZodObject<{
175
186
  email: z.ZodEmail;
176
187
  role_id: z.ZodUUID;
177
188
  expires_at: z.ZodISODateTime;
178
- accept_url: z.ZodNullable<z.ZodURL>;
189
+ accept_url: z.ZodURL;
179
190
  mail: z.ZodEnum<{
180
191
  sent: "sent";
181
192
  not_requested: "not_requested";
@@ -371,6 +382,65 @@ export declare const allowedOrigin: z.ZodString;
371
382
  * name limit.
372
383
  */
373
384
  export declare const emailDomain: z.ZodString;
385
+ /**
386
+ * **How an app's users sign in: by password, by emailed code, or both.**
387
+ *
388
+ * At least one is on — an app with neither would have no door but its
389
+ * identity providers, and a provider can be disabled. Identity providers are
390
+ * not part of this choice; they stay on top of whichever methods are on. A
391
+ * method turned off refuses its routes with `method_not_allowed`; a stored
392
+ * password stays stored, so turning the method back on restores it.
393
+ */
394
+ export declare const appSignInMethods: z.ZodObject<{
395
+ password: z.ZodBoolean;
396
+ email_code: z.ZodBoolean;
397
+ }, z.core.$strict>;
398
+ export type AppSignInMethods = z.infer<typeof appSignInMethods>;
399
+ /**
400
+ * **Whether an app asks its users for a second factor**, an authenticator
401
+ * app (TOTP) with ten single-use recovery codes.
402
+ *
403
+ * - `off` — nobody is asked to set one up, and nobody can.
404
+ * - `optional` — people turn it on in the app's own account settings.
405
+ * - `required` — a person without one sets it up at their next sign-in,
406
+ * before any session exists. Nobody is signed out when it is switched on.
407
+ *
408
+ * Whatever the policy, a person who **has** a confirmed authenticator is asked
409
+ * for a code at every sign-in that yields a session. A sign-in through an
410
+ * identity provider is never asked: the provider owns that sign-in.
411
+ */
412
+ export declare const appTwoFactorPolicy: z.ZodEnum<{
413
+ optional: "optional";
414
+ required: "required";
415
+ off: "off";
416
+ }>;
417
+ export type AppTwoFactorPolicy = z.infer<typeof appTwoFactorPolicy>;
418
+ /**
419
+ * **The app's own home page**: https, or http on `localhost`/`127.0.0.1` —
420
+ * the host rule `appUrlTemplate` keeps — and no placeholder, because nothing
421
+ * is substituted into it. The hosted pages link to it as `Open <app>` when a
422
+ * flow is done.
423
+ */
424
+ export declare const appHomeUrl: z.ZodURL;
425
+ /** The accent colour of the hosted pages: `#rrggbb`, lowercase, the one spelling the renderer compares against. */
426
+ export declare const hostedAccent: z.ZodString;
427
+ /** The largest logo the hosted pages take, in bytes: 100 KB. */
428
+ export declare const HOSTED_LOGO_MAX_BYTES = 102400;
429
+ /** The logo types the hosted pages take. An SVG is served sandboxed and embedded only as an image. */
430
+ export declare const HOSTED_LOGO_TYPES: readonly ["image/png", "image/svg+xml"];
431
+ /**
432
+ * **The Fleetless-hosted pages an unset URL falls back to**, one per URL
433
+ * field, as templates with the same placeholder the field takes. Read-only:
434
+ * they are minted by the cloud from the auth portal's base URL and the app's
435
+ * identifier.
436
+ */
437
+ export declare const appHostedPages: z.ZodObject<{
438
+ invite_url: z.ZodURL;
439
+ verify_url: z.ZodURL;
440
+ reset_url: z.ZodURL;
441
+ mcp_login_url: z.ZodURL;
442
+ }, z.core.$strip>;
443
+ export type AppHostedPages = z.infer<typeof appHostedPages>;
374
444
  /**
375
445
  * **The app's auth settings: one row per app, configured by a Fleetless user.**
376
446
  *
@@ -380,11 +450,11 @@ export declare const emailDomain: z.ZodString;
380
450
  * a developer inviting somebody by hand has already made the decision the
381
451
  * whitelist automates.
382
452
  *
383
- * The four URLs are what makes that work: Fleetless mails a link, and the link
384
- * points into the developer's app. An app that has configured none of them
385
- * still works for password login — it simply cannot send a mail that leads
386
- * anywhere, and `send_mail` is refused rather than silently sending a dead
387
- * link.
453
+ * The four URLs point Fleetless's mails and the MCP sign-in into the
454
+ * developer's app. **Each is optional**: an unset one falls back to the
455
+ * Fleetless-hosted page in `hosted_pages`, so nothing is refused for a
456
+ * missing URL — self-registration, mailed invitations, resets and MCP sign-in
457
+ * all work before the app has a page of its own.
388
458
  */
389
459
  export declare const appAuthConfig: z.ZodObject<{
390
460
  self_registration: z.ZodBoolean;
@@ -395,6 +465,24 @@ export declare const appAuthConfig: z.ZodObject<{
395
465
  verify_url: z.ZodNullable<z.ZodString>;
396
466
  reset_url: z.ZodNullable<z.ZodString>;
397
467
  mcp_login_url: z.ZodNullable<z.ZodString>;
468
+ app_url: z.ZodNullable<z.ZodURL>;
469
+ sign_in_methods: z.ZodObject<{
470
+ password: z.ZodBoolean;
471
+ email_code: z.ZodBoolean;
472
+ }, z.core.$strict>;
473
+ two_factor: z.ZodEnum<{
474
+ optional: "optional";
475
+ required: "required";
476
+ off: "off";
477
+ }>;
478
+ hosted_logo_url: z.ZodNullable<z.ZodURL>;
479
+ hosted_accent: z.ZodNullable<z.ZodString>;
480
+ hosted_pages: z.ZodObject<{
481
+ invite_url: z.ZodURL;
482
+ verify_url: z.ZodURL;
483
+ reset_url: z.ZodURL;
484
+ mcp_login_url: z.ZodURL;
485
+ }, z.core.$strip>;
398
486
  oidc_callback_url: z.ZodURL;
399
487
  updated_at: z.ZodISODateTime;
400
488
  }, z.core.$strip>;
@@ -403,8 +491,8 @@ export type AppAuthConfig = z.infer<typeof appAuthConfig>;
403
491
  * `PUT /api/apps/:id/auth-config/registration` — who may get in, and from
404
492
  * where.
405
493
  *
406
- * Three slices rather than one document, and each still a **replace** with
407
- * every field of its slice required: three screens carving up one
494
+ * Several slices rather than one document, and each still a **replace** with
495
+ * every field of its slice required: several screens carving up one
408
496
  * all-required request is how a field nobody's screen shows becomes a field
409
497
  * somebody's save clears. The slice states its own ownership, so a new field
410
498
  * lands in one schema and one screen.
@@ -418,33 +506,59 @@ export declare const putAppAuthRegistrationRequest: z.ZodObject<{
418
506
  allowed_origins: z.ZodArray<z.ZodString>;
419
507
  }, z.core.$strict>;
420
508
  export type PutAppAuthRegistrationRequest = z.infer<typeof putAppAuthRegistrationRequest>;
421
- /** `PUT /api/apps/:id/auth-config/urls` — the three pages Fleetless's mails point at. */
509
+ /** `PUT /api/apps/:id/auth-config/sign-in` — how the app's users sign in, and whether they give a second factor. */
510
+ export declare const putAppAuthSignInRequest: z.ZodObject<{
511
+ two_factor: z.ZodEnum<{
512
+ optional: "optional";
513
+ required: "required";
514
+ off: "off";
515
+ }>;
516
+ sign_in_methods: z.ZodObject<{
517
+ password: z.ZodBoolean;
518
+ email_code: z.ZodBoolean;
519
+ }, z.core.$strict>;
520
+ }, z.core.$strict>;
521
+ export type PutAppAuthSignInRequest = z.infer<typeof putAppAuthSignInRequest>;
522
+ /**
523
+ * `PUT /api/apps/:id/auth-config/urls` — the app's home page and the four
524
+ * pages Fleetless's mails and the MCP sign-in point at. One slice, because
525
+ * the console's Pages section owns all five; each `null` falls back to the
526
+ * hosted page.
527
+ */
422
528
  export declare const putAppAuthUrlsRequest: z.ZodObject<{
423
529
  invite_url: z.ZodNullable<z.ZodString>;
424
530
  verify_url: z.ZodNullable<z.ZodString>;
425
531
  reset_url: z.ZodNullable<z.ZodString>;
532
+ mcp_login_url: z.ZodNullable<z.ZodString>;
533
+ app_url: z.ZodNullable<z.ZodURL>;
426
534
  }, z.core.$strict>;
427
535
  export type PutAppAuthUrlsRequest = z.infer<typeof putAppAuthUrlsRequest>;
428
536
  /**
429
- * `PUT /api/apps/:id/auth-config/mcp` — the switch and the login URL, which
430
- * belong together: on without a URL refuses every sign-in, in the MCP
431
- * client's browser mid-OAuth, where no console screen ever sees it.
537
+ * `PUT /api/apps/:id/auth-config/mcp` — the switch alone. Its login URL moved
538
+ * to the `urls` slice: on without a URL no longer refuses anything, because
539
+ * the hosted MCP sign-in stands in for it.
432
540
  */
433
541
  export declare const putAppAuthMcpRequest: z.ZodObject<{
434
542
  mcp_enabled: z.ZodBoolean;
435
- mcp_login_url: z.ZodNullable<z.ZodString>;
436
543
  }, z.core.$strict>;
437
544
  export type PutAppAuthMcpRequest = z.infer<typeof putAppAuthMcpRequest>;
545
+ /** `PUT /api/apps/:id/auth-config/look` — the hosted pages' accent colour. The logo is its own write, a raw image body. */
546
+ export declare const putAppAuthLookRequest: z.ZodObject<{
547
+ hosted_accent: z.ZodNullable<z.ZodString>;
548
+ }, z.core.$strict>;
549
+ export type PutAppAuthLookRequest = z.infer<typeof putAppAuthLookRequest>;
438
550
  /**
439
- * The three mails a developer may replace with their own template.
440
- * Mails to *Fleetless* users — a team invitation, a console password reset —
441
- * stay Fleetless default and are deliberately not customisable: they are
442
- * about this platform, not about the developer's product.
551
+ * The four mails a developer may replace with their own template: the
552
+ * invitation, the address confirmation, the password reset and the sign-in
553
+ * code. Mails to *Fleetless* users — a team invitation, a console sign-in
554
+ * code — stay Fleetless default and are deliberately not customisable: they
555
+ * are about this platform, not about the developer's product.
443
556
  */
444
557
  export declare const mailTemplateKind: z.ZodEnum<{
445
558
  invite: "invite";
446
559
  verify: "verify";
447
560
  reset: "reset";
561
+ login_code: "login_code";
448
562
  }>;
449
563
  export type MailTemplateKind = z.infer<typeof mailTemplateKind>;
450
564
  /**
@@ -456,9 +570,9 @@ export type MailTemplateKind = z.infer<typeof mailTemplateKind>;
456
570
  * where the renderer, the console's completion and the docs all read the same
457
571
  * one.
458
572
  */
459
- export declare const MAIL_TEMPLATE_VARIABLES: readonly ["app.name", "org.name", "user.email", "user.display_name", "role.name", "link", "expires_in_hours"];
573
+ export declare const MAIL_TEMPLATE_VARIABLES: readonly ["app.name", "org.name", "user.email", "user.display_name", "role.name", "link", "expires_in_hours", "code", "expires_in_minutes"];
460
574
  /**
461
- * **The Fleetless default text for the three app mails.**
575
+ * **The Fleetless default text for the four app mails.**
462
576
  *
463
577
  * It lives here rather than in the cloud because two products send the same
464
578
  * words: the cloud renders these when an app has no template of its own, and
@@ -492,12 +606,15 @@ export declare const MAIL_TEMPLATE_VARIABLES: readonly ["app.name", "org.name",
492
606
  * that one is written by an authenticated developer about somebody they
493
607
  * invited.
494
608
  *
495
- * **`expires_in_hours` is the only lifetime variable a template gets**, and
609
+ * **`expires_in_hours` is the lifetime variable of the three link mails**, and
496
610
  * the three values are 1, 24 and 168. "The next 168 hours" is not how a person
497
611
  * says a week, so each default converts: 48 and up reads in days, exactly one
498
612
  * reads "1 hour", everything else reads in hours. The conversion is in the
499
613
  * template rather than in a new variable because a custom template has the
500
- * same problem and this is the spelling it can copy.
614
+ * same problem and this is the spelling it can copy. The sign-in code mail
615
+ * carries no link: it names the `code` and its lifetime in
616
+ * `expires_in_minutes` (10), and greets nobody, since whoever asked for it
617
+ * typed the address unauthenticated.
501
618
  *
502
619
  * **What contracts does NOT assert about these.** That they compile as Liquid
503
620
  * is the cloud's business — contracts has no renderer and adding one to check
@@ -520,6 +637,7 @@ export declare const appMailTemplate: z.ZodObject<{
520
637
  invite: "invite";
521
638
  verify: "verify";
522
639
  reset: "reset";
640
+ login_code: "login_code";
523
641
  }>;
524
642
  subject: z.ZodString;
525
643
  text: z.ZodString;
@@ -534,6 +652,7 @@ export declare const appMailTemplateListResponse: z.ZodObject<{
534
652
  invite: "invite";
535
653
  verify: "verify";
536
654
  reset: "reset";
655
+ login_code: "login_code";
537
656
  }>;
538
657
  subject: z.ZodString;
539
658
  text: z.ZodString;