@omelhorsite/sdk 0.3.0 → 0.4.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 (92) hide show
  1. package/README.md +113 -131
  2. package/dist/index.js +1049 -1246
  3. package/dist/types/auth/device.d.ts +1 -1
  4. package/dist/types/auth/index.d.ts +2 -2
  5. package/dist/types/auth/tokens.d.ts +15 -15
  6. package/dist/types/client.d.ts +10 -10
  7. package/dist/types/errors.d.ts +12 -15
  8. package/dist/types/http.d.ts +74 -118
  9. package/dist/types/index.d.ts +2 -2
  10. package/dist/types/internal/attachments.d.ts +17 -0
  11. package/dist/types/internal/helpers.d.ts +9 -0
  12. package/dist/types/listing.d.ts +90 -0
  13. package/dist/types/local/qr.d.ts +1 -1
  14. package/dist/types/local/wordlist.d.ts +2 -3
  15. package/dist/types/resources/account.d.ts +19 -19
  16. package/dist/types/resources/admin/authorizedApplications.d.ts +133 -0
  17. package/dist/types/resources/admin/chests.d.ts +51 -0
  18. package/dist/types/resources/admin/eventAlerts.d.ts +60 -0
  19. package/dist/types/resources/admin/identities.d.ts +99 -0
  20. package/dist/types/resources/admin/index.d.ts +77 -0
  21. package/dist/types/resources/admin/jobs.d.ts +97 -0
  22. package/dist/types/resources/admin/myOauthApplications.d.ts +282 -0
  23. package/dist/types/resources/admin/notepads.d.ts +49 -0
  24. package/dist/types/resources/admin/oauthApplications.d.ts +309 -0
  25. package/dist/types/resources/admin/quotas.d.ts +114 -0
  26. package/dist/types/resources/admin/shortLinks.d.ts +201 -0
  27. package/dist/types/resources/admin/types.d.ts +222 -0
  28. package/dist/types/resources/admin/vocalSeparations.d.ts +98 -0
  29. package/dist/types/resources/admin.d.ts +17 -13
  30. package/dist/types/resources/auth/index.d.ts +1 -1
  31. package/dist/types/resources/auth/passkeys.d.ts +127 -163
  32. package/dist/types/resources/auth/sessions.d.ts +116 -161
  33. package/dist/types/resources/chests.d.ts +27 -31
  34. package/dist/types/resources/content/analysis.d.ts +62 -0
  35. package/dist/types/resources/content/blogs.d.ts +471 -0
  36. package/dist/types/resources/content/feedbacks.d.ts +263 -0
  37. package/dist/types/resources/content/index.d.ts +52 -0
  38. package/dist/types/resources/content/intel/articles.d.ts +230 -0
  39. package/dist/types/resources/content/intel/config.d.ts +135 -0
  40. package/dist/types/resources/content/intel/index.d.ts +53 -0
  41. package/dist/types/resources/content/intel/items.d.ts +91 -0
  42. package/dist/types/resources/content/intel/reports.d.ts +108 -0
  43. package/dist/types/resources/content/intel/scripts.d.ts +152 -0
  44. package/dist/types/resources/content/intel/sources.d.ts +236 -0
  45. package/dist/types/resources/content/intel/stats.d.ts +105 -0
  46. package/dist/types/resources/content/intel/types.d.ts +86 -0
  47. package/dist/types/resources/content/jokes.d.ts +93 -0
  48. package/dist/types/resources/content/notifications.d.ts +147 -0
  49. package/dist/types/resources/content/serviceUsages.d.ts +73 -0
  50. package/dist/types/resources/content/servicesStatus.d.ts +194 -0
  51. package/dist/types/resources/content/siteConfig.d.ts +43 -0
  52. package/dist/types/resources/content/spaceInvaders.d.ts +154 -0
  53. package/dist/types/resources/content.d.ts +41 -236
  54. package/dist/types/resources/dynamicQrs.d.ts +29 -45
  55. package/dist/types/resources/forms.d.ts +37 -58
  56. package/dist/types/resources/jobs.d.ts +35 -44
  57. package/dist/types/resources/library/annotations.d.ts +162 -0
  58. package/dist/types/resources/library/books.d.ts +534 -0
  59. package/dist/types/resources/library/chat.d.ts +259 -0
  60. package/dist/types/resources/library/index.d.ts +39 -0
  61. package/dist/types/resources/library/shelves.d.ts +237 -0
  62. package/dist/types/resources/library/types.d.ts +120 -0
  63. package/dist/types/resources/library.d.ts +20 -22
  64. package/dist/types/resources/media.d.ts +48 -61
  65. package/dist/types/resources/movies/addons.d.ts +388 -0
  66. package/dist/types/resources/movies/collections.d.ts +352 -0
  67. package/dist/types/resources/movies/index.d.ts +29 -0
  68. package/dist/types/resources/movies/types.d.ts +50 -0
  69. package/dist/types/resources/movies/watchProgress.d.ts +277 -0
  70. package/dist/types/resources/movies.d.ts +27 -53
  71. package/dist/types/resources/music/artists.d.ts +182 -246
  72. package/dist/types/resources/music/imports.d.ts +190 -218
  73. package/dist/types/resources/music/index.d.ts +8 -7
  74. package/dist/types/resources/music/playlists.d.ts +85 -117
  75. package/dist/types/resources/music/social.d.ts +153 -228
  76. package/dist/types/resources/music/songs.d.ts +165 -227
  77. package/dist/types/resources/realtime.d.ts +75 -88
  78. package/dist/types/resources/shortLinks.d.ts +38 -47
  79. package/dist/types/resources/social/groupChats.d.ts +458 -0
  80. package/dist/types/resources/social/index.d.ts +19 -0
  81. package/dist/types/resources/social/messages.d.ts +424 -0
  82. package/dist/types/resources/social/relationships.d.ts +322 -0
  83. package/dist/types/resources/social/types.d.ts +37 -0
  84. package/dist/types/resources/social.d.ts +21 -3
  85. package/dist/types/resources/storage/upload.d.ts +42 -56
  86. package/dist/types/resources/storage.d.ts +94 -109
  87. package/dist/types/resources/tickets.d.ts +19 -10
  88. package/dist/types/resources/tools/backgroundRemoval.d.ts +11 -13
  89. package/dist/types/resources/tools/captions.d.ts +107 -135
  90. package/dist/types/resources/tools/upscale.d.ts +12 -16
  91. package/dist/types/types.d.ts +29 -38
  92. package/package.json +1 -1
@@ -13,9 +13,9 @@
13
13
  * | `POST /authentication_options` | **none** | **20/min per IP** |
14
14
  * | `POST /authentication` | **none** | **20/min per IP** |
15
15
  *
16
- * The last two share ONE bucket, not one each: `rack_attack.rb` throttles on
17
- * `canonical_path(req).start_with?("/webauthn_credentials/authentication")`,
18
- * and `/authentication_options` starts with that string. Twenty POSTs a minute
16
+ * The last two share ONE bucket, not one each: the throttle matches every
17
+ * path that starts with `/webauthn_credentials/authentication`, and
18
+ * `/authentication_options` starts with that string. Twenty POSTs a minute
19
19
  * from an IP covers both halves of every login attempt, so a NATed office gets
20
20
  * ten sign-ins a minute between them. Budget accordingly, and see the note on
21
21
  * {@link PasskeysNamespace.authenticate} for why neither of those two methods
@@ -29,16 +29,12 @@
29
29
  * say so in those words. It says `500`, or it says "Passkey could not be
30
30
  * verified", two minutes after the user pressed their fingerprint.
31
31
  *
32
- * The SDK's one body-shaped rewrite is the null sentinel, and this namespace is
33
- * out of its reach BY CONSTRUCTION rather than by opting out: `NULL_SENTINEL`
34
- * is written by `encodeQuery` in `http.ts` and by nothing else. A JSON body
35
- * goes through `JSON.stringify` untouched (`ApiClient#buildInit`), and
36
- * `buildFormData` omits a null field rather than sentinelling it. So the escape
37
- * hatch is simply this: a ceremony travels in the BODY, never in `query`, and
38
- * every method here passes the caller's object straight to `http.post` with no
39
- * copy, no reshaping, and no key filtering. `test/passkeys.test.ts` pins the
40
- * serialised body byte for byte, including a `null` that must survive as
41
- * `null`.
32
+ * The SDK's one body-shaped rewrite is the null sentinel, and it is written
33
+ * into query strings only, never into a JSON body. A ceremony travels in the
34
+ * BODY, and every method here passes the caller's object straight to
35
+ * `http.post` with no copy, no reshaping, and no key filtering: a `null`
36
+ * inside survives as `null`. `test/passkeys.test.ts` pins the serialised body
37
+ * byte for byte.
42
38
  *
43
39
  * The corollary is that nothing here normalises for you either. If your
44
40
  * platform is loose about base64 padding, run the credential through
@@ -51,15 +47,14 @@
51
47
  *
52
48
  * It never calls `navigator.credentials` and never touches a native passkey
53
49
  * module. That is the host's job, in the host's runtime, and it is the half
54
- * that differs between the three clients:
50
+ * that differs between runtimes:
55
51
  *
56
52
  * - browser: `@simplewebauthn/browser`'s `startRegistration` /
57
53
  * `startAuthentication`, which take `optionsJSON` in the exact shape
58
54
  * {@link PasskeyRegistrationOptions} / {@link PasskeyAuthenticationOptions}
59
55
  * describe and hand back the exact shape the credential types describe;
60
- * - React Native: `react-native-passkeys`, loaded lazily because
61
- * `requireNativeModule` throws at import time when the module is not linked
62
- * (Expo Go, a stale dev client);
56
+ * - React Native: `react-native-passkeys`, best loaded lazily because it
57
+ * throws at import time when the native module is not linked;
63
58
  * - Bun / a Worker: there is no authenticator. `list` and `remove` work,
64
59
  * the ceremonies cannot.
65
60
  *
@@ -69,41 +64,35 @@ import { Resource } from "../../http";
69
64
  import type { AccountSession } from "../account";
70
65
  import type { BaseRecord, Id, RequestOptions, Timestamp } from "../../types";
71
66
  /**
72
- * One registered passkey, as `WebauthnCredentialBlueprint` renders it.
73
- *
74
- * The blueprint declares two fields and inherits three from
75
- * `ApplicationBlueprint`, so the payload is exactly `id`, `created_at`,
76
- * `updated_at`, `nickname`, `last_used_at`. Its `:extended` view is an empty
77
- * block, which in Blueprinter INHERITS the default view rather than replacing
78
- * it, so `:extended` and the default are the same five fields here: the row
79
- * `POST /registration` answers with and the rows `GET /` answers with are
80
- * identical, despite the controller asking for different views.
81
- *
82
- * Nothing about the credential itself is ever rendered. `external_id`,
83
- * `public_key` and `sign_count` stay on the server; there is no field here that
84
- * identifies the authenticator, so a UI cannot say "your YubiKey" or "this
85
- * phone" unless the user typed a nickname.
86
- *
87
- * `id` is a STRING (`create_table :webauthn_credentials, id: :string`), like
88
- * users and sessions and unlike songs and playlists. Never do arithmetic on it.
67
+ * One registered passkey.
68
+ *
69
+ * The payload is exactly `id`, `created_at`, `updated_at`, `nickname`,
70
+ * `last_used_at`, and it is the same five fields whether it came from
71
+ * `POST /registration` or from `GET /`.
72
+ *
73
+ * Nothing about the credential itself is ever rendered. The credential id,
74
+ * the public key and the sign counter stay on the server; there is no field
75
+ * here that identifies the authenticator, so a UI cannot say "your YubiKey"
76
+ * or "this phone" unless the user typed a nickname.
77
+ *
78
+ * `id` is a STRING, like users and sessions and unlike songs and playlists.
79
+ * Never do arithmetic on it.
89
80
  */
90
81
  export interface Passkey extends BaseRecord {
91
82
  /**
92
83
  * User-chosen label, or `null`.
93
84
  *
94
- * `normalizes :nickname, with: ->(n) { n.to_s.strip.presence }` runs on the
95
- * model, so `" "` is stored as `null` and comes back as `null`, not as the
96
- * spaces that were sent. A UI that echoes what it just submitted will show
97
- * the wrong thing; read the answer instead.
85
+ * The server trims it and stores a blank as `null`, so `" "` comes back as
86
+ * `null`, not as the spaces that were sent. A UI that echoes what it just
87
+ * submitted will show the wrong thing; read the answer instead.
98
88
  */
99
89
  readonly nickname: string | null;
100
90
  /**
101
91
  * When this passkey last completed a sign-in, or `null` if it never has.
102
92
  *
103
- * Written by `touch_usage!` through `update_columns`, which skips validations
104
- * AND callbacks but does bump `updated_at` by hand, so a passkey's
105
- * `updated_at` tracks its last use rather than its last edit. There is no
106
- * edit: the record has no update route.
93
+ * Every sign-in also bumps `updated_at`, so a passkey's `updated_at` tracks
94
+ * its last use rather than its last edit. There is no edit: the record has
95
+ * no update route.
107
96
  */
108
97
  readonly last_used_at: Timestamp | null;
109
98
  }
@@ -111,16 +100,15 @@ export interface Passkey extends BaseRecord {
111
100
  * What `POST /webauthn_credentials/authentication` answers with: the session,
112
101
  * plus the token, exactly as `POST /sessions` answers a password sign-in.
113
102
  *
114
- * `SessionBlueprint`'s `:token` view adds one field to the base view, so this
115
- * is an {@link AccountSession} with a `token`. That token is the new
103
+ * This is an {@link AccountSession} with a `token`. That token is the new
116
104
  * credential, and it is shown ONCE. Persist it here or lose it.
117
105
  *
118
- * A browser gets the same token a second way, as an httpOnly cookie the
119
- * controller sets alongside the body (`set_session_cookie`). That is why the
120
- * web client can ignore `token` entirely and still be signed in after the
121
- * post-login reload: it authenticates by cookie and deliberately never stores a
122
- * token where a script could read it. A native or CLI client does the opposite
123
- * and reads `token`.
106
+ * A browser gets the same token a second way, as an httpOnly cookie set
107
+ * alongside the body. That is why a cookie-mode client can ignore `token`
108
+ * entirely and still be signed in after the post-login reload: it
109
+ * authenticates by cookie and deliberately never stores a token where a
110
+ * script could read it. A token-mode client does the opposite and reads
111
+ * `token`.
124
112
  */
125
113
  export interface PasskeySession extends AccountSession {
126
114
  /** The bearer token for the new session. Rendered once, here, and never again. */
@@ -129,10 +117,8 @@ export interface PasskeySession extends AccountSession {
129
117
  /**
130
118
  * An `ArrayBuffer` after the only encoding this API speaks: unpadded base64url.
131
119
  *
132
- * `config.encoding = :base64url` in `config/initializers/webauthn.rb` decides
133
- * this for BOTH directions. Everything the server sends
134
- * (`WebAuthn::Encoders::Base64UrlEncoder#encode`) has its `=` padding chomped
135
- * off, and everything it reads back it decodes the same way.
120
+ * The server uses it in BOTH directions: everything it sends has its `=`
121
+ * padding chomped off, and everything it reads back it decodes the same way.
136
122
  *
137
123
  * A type alias, not a branded type, because a brand would force every caller to
138
124
  * cast the strings their platform just handed them and would buy nothing: the
@@ -153,24 +139,21 @@ export type PasskeyTransport = "usb" | "nfc" | "ble" | "smart-card" | "hybrid" |
153
139
  * One credential the ceremony should exclude (registration) or allow
154
140
  * (authentication).
155
141
  *
156
- * The server builds these with `as_public_key_descriptors`, which emits `type`
157
- * and `id` and NEVER `transports`, so a descriptor that arrives from this API
158
- * has exactly two keys. `transports` is here for the other direction, where a
159
- * platform reports it.
142
+ * The server emits `type` and `id` and NEVER `transports`, so a descriptor
143
+ * that arrives from this API has exactly two keys. `transports` is here for
144
+ * the other direction, where a platform reports it.
160
145
  */
161
146
  export interface PasskeyCredentialDescriptor {
162
147
  readonly type: "public-key";
163
- /** The credential id, base64url. Matches `webauthn_credentials.external_id`. */
148
+ /** The credential id, base64url. */
164
149
  readonly id: PasskeyBase64Url;
165
150
  readonly transports?: readonly PasskeyTransport[];
166
151
  }
167
- /** The relying party, from `WebAuthn.configure`: `"O Melhor Site"` at `omelhorsite.pt`. */
152
+ /** The relying party: `"O Melhor Site"` at `omelhorsite.pt`. */
168
153
  export interface PasskeyRelyingParty {
169
154
  readonly name: string;
170
155
  /**
171
- * The registrable domain that owns the credential. Always sent: the
172
- * initializer sets `rp_id`, and `RPEntity` falls back to it when the caller
173
- * gives none.
156
+ * The registrable domain that owns the credential. Always sent.
174
157
  *
175
158
  * It is the domain of the UI, NOT of the API. Passkeys minted here are scoped
176
159
  * to `omelhorsite.pt` and its subdomains; `backend.omelhorsite.pt` serves the
@@ -181,9 +164,9 @@ export interface PasskeyRelyingParty {
181
164
  /**
182
165
  * The account the passkey will belong to.
183
166
  *
184
- * `id` is `users.webauthn_id`, a server-minted opaque handle that exists for
185
- * exactly this purpose, assigned lazily on the first call to
186
- * {@link PasskeysNamespace.registrationOptions}. It is NOT `users.id`, and the
167
+ * `id` is a server-minted opaque handle that exists for exactly this purpose,
168
+ * assigned lazily on the first call to
169
+ * {@link PasskeysNamespace.registrationOptions}. It is NOT the user's `id`, and the
187
170
  * distinction is the point: the value is stored on the authenticator, is
188
171
  * readable by anyone who gets hold of the device, and must therefore say
189
172
  * nothing about the account. `name` and `displayName`, by contrast, ARE the
@@ -211,26 +194,23 @@ export interface PasskeyAuthenticatorSelection {
211
194
  }
212
195
  /**
213
196
  * `POST /webauthn_credentials/registration_options` - the arguments for
214
- * `navigator.credentials.create()`, camelCased and base64url-encoded by the
215
- * gem's `JSONSerializer`.
197
+ * `navigator.credentials.create()`, camelCased and base64url-encoded.
216
198
  *
217
- * Every optional field below is optional because `JSONSerializer#to_hash` drops
218
- * a falsy attribute, not because this deployment sometimes omits it. What this
219
- * deployment actually sends, verified against
220
- * `WebAuthn::PublicKeyCredential::CreationOptions`:
199
+ * Every optional field below is optional because the server drops a falsy
200
+ * attribute, not because it sometimes omits a field on purpose. What it
201
+ * actually sends:
221
202
  *
222
203
  * - `challenge`, `timeout` (120000), `extensions` (`{}`), `rp`, `user`,
223
204
  * `pubKeyCredParams` (ES256, PS256, RS256), `authenticatorSelection`
224
205
  * (`residentKey` and `userVerification`, both `"preferred"`), and
225
206
  * `excludeCredentials`, which is `[]` for an account with no passkeys yet
226
207
  * rather than absent;
227
- * - NOT `attestation`. The controller passes none, so the key is dropped
228
- * entirely and the platform applies its own default (`"none"`).
208
+ * - NOT `attestation`. The key is absent, so the platform applies its own
209
+ * default (`"none"`).
229
210
  *
230
211
  * Pass this object to the platform whole. Do not rebuild it field by field
231
- * unless your platform needs you to: the app does exactly that, and its reason
232
- * is a native Record decoder that trips on `extensions: {}`, which is a
233
- * property of `react-native-passkeys` rather than of WebAuthn.
212
+ * unless your platform needs you to: `react-native-passkeys` does, because its
213
+ * native Record decoder trips on `extensions: {}`.
234
214
  */
235
215
  export interface PasskeyRegistrationOptions {
236
216
  readonly challenge: PasskeyBase64Url;
@@ -257,15 +237,14 @@ export interface PasskeyRegistrationOptions {
257
237
  * `options` from `POST /webauthn_credentials/authentication_options` - the
258
238
  * arguments for `navigator.credentials.get()`.
259
239
  *
260
- * `allowCredentials` is always present and always `[]`: the controller calls
261
- * `options_for_get(user_verification: "preferred")` with no allow list, and
262
- * `RequestOptions#allow_credentials` falls back to `[]` rather than to nil. An
263
- * empty allow list IS the feature - it makes the ceremony discoverable, so the
264
- * OS offers whatever passkeys it holds for the domain and the user picks an
240
+ * `allowCredentials` is always present and always `[]`: the server sends no
241
+ * allow list, and spells that as `[]` rather than omitting the key. An empty
242
+ * allow list IS the feature - it makes the ceremony discoverable, so the OS
243
+ * offers whatever passkeys it holds for the domain and the user picks an
265
244
  * account. That is why sign-in needs no email field.
266
245
  *
267
- * `rpId` is always present too (`RequestOptions` defaults it from the
268
- * relying party), which matters because `react-native-passkeys` requires it.
246
+ * `rpId` is always present too, which matters because `react-native-passkeys`
247
+ * requires it.
269
248
  */
270
249
  export interface PasskeyAuthenticationOptions {
271
250
  readonly challenge: PasskeyBase64Url;
@@ -282,10 +261,10 @@ export interface PasskeyAuthenticationOptions {
282
261
  * the ceremony arguments plus the handle that identifies the challenge.
283
262
  *
284
263
  * The handle exists because the login ceremony has no session to key a
285
- * challenge against. The server caches the challenge under
286
- * `webauthn:auth:<handle>` and hands you the handle; you give it back with the
287
- * assertion. Treat it as a single-use nonce: it is a `SecureRandom.uuid`, it
288
- * lives two minutes, and {@link PasskeysNamespace.authenticate} spends it.
264
+ * challenge against. The server keeps the challenge under the handle and hands
265
+ * you the handle; you give it back with the assertion. Treat it as a
266
+ * single-use nonce: it is a random UUID, it lives two minutes, and
267
+ * {@link PasskeysNamespace.authenticate} spends it.
289
268
  */
290
269
  export interface PasskeyAuthenticationChallenge {
291
270
  readonly handle: string;
@@ -295,14 +274,11 @@ export interface PasskeyAuthenticationChallenge {
295
274
  * What the authenticator produced during registration, ready to be posted back.
296
275
  *
297
276
  * `id` and `rawId` are BOTH required, and both must be the same credential id
298
- * in base64url. This is not belt-and-braces, it is
299
- * `WebAuthn::PublicKeyCredential#valid_id?`, which decodes each one separately
300
- * and compares the BYTES. Send them out of step and see the warning on
301
- * {@link PasskeysNamespace.register}: the mismatch raises a bare `RuntimeError`
302
- * inside the gem, which is not a `WebAuthn::Error`, so the controller's rescue
303
- * does not catch it and you get a `500`.
304
- *
305
- * The gem reads `clientDataJSON`, `attestationObject` and `transports` from
277
+ * in base64url. This is not belt-and-braces: the server decodes each one
278
+ * separately and compares the BYTES. Send them out of step and you get a
279
+ * `500`, not a `400` - see the warning on {@link PasskeysNamespace.register}.
280
+ *
281
+ * The server reads `clientDataJSON`, `attestationObject` and `transports` from
306
282
  * `response` and ignores anything else in it, so a browser's `getPublicKey()` /
307
283
  * `publicKey` extras are harmless. They are also pointless bytes on a phone's
308
284
  * connection.
@@ -328,8 +304,8 @@ export interface PasskeyRegistrationCredential {
328
304
  * consequence for getting it wrong.
329
305
  *
330
306
  * `userHandle` is what a discoverable ceremony returns as the account the user
331
- * picked, and this server does NOT read it: it looks the credential up by
332
- * `external_id` instead. Send it anyway if the platform gave you one, but do
307
+ * picked, and this server does NOT read it: it looks the credential up by its
308
+ * id instead. Send it anyway if the platform gave you one, but do
333
309
  * not synthesise one, and never treat its absence as a failure.
334
310
  */
335
311
  export interface PasskeyAssertionCredential {
@@ -351,8 +327,8 @@ export interface RegisterPasskeyInput {
351
327
  /** The attestation the platform just produced. Sent verbatim. */
352
328
  readonly credential: PasskeyRegistrationCredential;
353
329
  /**
354
- * Optional label. Blank and whitespace-only strings are stored as `null` by
355
- * the model's `normalizes`, so there is no point sending `" "` to clear
330
+ * Optional label. Blank and whitespace-only strings are stored as `null`,
331
+ * so there is no point sending `" "` to clear
356
332
  * anything - there is nothing to clear, the record cannot be updated.
357
333
  */
358
334
  readonly nickname?: string;
@@ -373,15 +349,15 @@ export interface AuthenticatePasskeyInput {
373
349
  * ## Who needs this
374
350
  *
375
351
  * A browser does not. `@simplewebauthn/browser` already emits unpadded
376
- * base64url on both sides, which is why the web frontend posts its credential
377
- * straight through and has never needed a normaliser.
352
+ * base64url on both sides, so a browser credential can be posted straight
353
+ * through.
378
354
  *
379
355
  * React Native does. Each platform re-encodes in its own native layer on the
380
356
  * way out of the OS, and they do not agree with each other about padding; iOS
381
357
  * in particular re-pads on the way in and strips on the way out. That would be
382
- * harmless if the server were lenient, and on most fields it is - the gem's
383
- * decoder re-pads a short string and accepts either alphabet. It is NOT lenient
384
- * about one thing: `valid_id?` decodes `id` and `rawId` SEPARATELY and demands
358
+ * harmless if the server were lenient, and on most fields it is - it re-pads a
359
+ * short string and accepts either alphabet. It is NOT lenient about one
360
+ * thing: it decodes `id` and `rawId` SEPARATELY and demands
385
361
  * identical bytes, so a platform that pads one and not the other loses the
386
362
  * ceremony at the very last step, with a 500 and nothing in the message.
387
363
  *
@@ -414,9 +390,9 @@ export declare function isPasskeyBase64Url(value: unknown): value is PasskeyBase
414
390
  * thing that must not happen behind a caller's back.
415
391
  *
416
392
  * Drops `getPublicKey`, `publicKey`, `getPublicKeyAlgorithm` and
417
- * `getAuthenticatorData` from `response`: `AuthenticatorAttestationResponse`
418
- * reads `clientDataJSON`, `attestationObject` and `transports` and nothing
419
- * else, and the dropped fields are large.
393
+ * `getAuthenticatorData` from `response`: the server reads `clientDataJSON`,
394
+ * `attestationObject` and `transports` and nothing else, and the dropped
395
+ * fields are large.
420
396
  *
421
397
  * @throws {TypeError} through {@link passkeyBase64Url} when a required field is
422
398
  * missing or not base64.
@@ -441,22 +417,18 @@ export declare class PasskeysNamespace extends Resource {
441
417
  * `GET /webauthn_credentials` - every passkey of the signed-in user, newest
442
418
  * first.
443
419
  *
444
- * Returns a plain array, and that is the whole story: this action is
445
- * hand-written rather than `CrudActions`, so unlike almost every other index
446
- * in this API it has NO list DSL, NO `modifiers[page]`, NO `search` /
447
- * `exact_search`, and NO `ETag` / `304`. Sending those parameters is not an
448
- * error either - the controller never looks at `params`, so
449
- * `reject_unknown_filter_keys!` is not in the chain and a filter is silently
450
- * ignored rather than rejected with a `400`. The web frontend does exactly
451
- * that today: `PasskeyService.list` accepts a `ListFilters` argument and
452
- * forwards it, and it has never had any effect.
420
+ * Returns a plain array, and that is the whole story: unlike almost every
421
+ * other index in this API it has NO list DSL, NO `modifiers[page]`, NO
422
+ * `search` / `exact_search`, and NO `ETag` / `304`. Sending those parameters
423
+ * is not an error either: a filter is silently ignored rather than rejected
424
+ * with a `400`.
453
425
  *
454
426
  * Hence no `Paginated` and no `PageParams` here. An account's passkey count
455
427
  * is bounded by how many devices a person owns, and the server would return
456
428
  * all of them regardless of what was asked.
457
429
  *
458
- * The order is `created_at: :desc`, applied in SQL, so it does not change if
459
- * a passkey is used.
430
+ * The order is newest-created first, so it does not change when a passkey
431
+ * is used.
460
432
  *
461
433
  * Requires a credential. General authenticated ceiling, 600/min.
462
434
  *
@@ -466,11 +438,9 @@ export declare class PasskeysNamespace extends Resource {
466
438
  /**
467
439
  * `DELETE /webauthn_credentials/:id` - removes one passkey. `204`, no body.
468
440
  *
469
- * The lookup is scoped to the caller (`Current.user.webauthn_credentials`),
470
- * so somebody else's id is a `404` and never a `403`: the endpoint does not
471
- * confirm that the id exists. `destroyable_by?` additionally lets an admin
472
- * through, but only for a passkey they can already find, which by that
473
- * scoping means their own.
441
+ * The lookup is scoped to the caller, so somebody else's id is a `404` and
442
+ * never a `403`: the endpoint does not confirm that the id exists. An
443
+ * administrator is no exception.
474
444
  *
475
445
  * Nothing stops the last passkey being removed. There is no "you would lock
476
446
  * yourself out" guard, because passwords and OAuth identities are still
@@ -493,19 +463,18 @@ export declare class PasskeysNamespace extends Resource {
493
463
  *
494
464
  * Two side effects, both of which matter:
495
465
  *
496
- * 1. **It assigns `users.webauthn_id` on first use.** An account that has
497
- * never touched passkeys gets one minted here (`WebAuthn.generate_user_id`,
498
- * written with `update_column`, so no callbacks and no `updated_at` bump).
499
- * That handle is then permanent and is what every passkey on this account
500
- * is bound to.
501
- * 2. **It caches a challenge under a key that is per USER, not per call**
502
- * (`webauthn:reg:<user id>`). Calling this twice for one account
466
+ * 1. **It assigns the account's WebAuthn user handle on first use.** An
467
+ * account that has never touched passkeys gets one minted here. That
468
+ * handle is then permanent and is what every passkey on this account is
469
+ * bound to.
470
+ * 2. **It caches a challenge under a key that is per USER, not per call.**
471
+ * Calling this twice for one account
503
472
  * OVERWRITES the first challenge, so two registrations in flight at once
504
473
  * means the older one fails verification with "Registration challenge
505
474
  * expired" even though nothing expired. Do not call it speculatively, do
506
475
  * not call it to warm a screen, and do not let a button fire it twice.
507
476
  *
508
- * The challenge lives **two minutes** (`CHALLENGE_TTL`), and the `timeout`
477
+ * The challenge lives **two minutes**, and the `timeout`
509
478
  * inside the options is also 120000. Those are the same number, and the cache
510
479
  * clock starts BEFORE the response is even sent, so a user who lets the OS
511
480
  * sheet sit open for its full advertised timeout arrives after the challenge
@@ -513,7 +482,7 @@ export declare class PasskeysNamespace extends Resource {
513
482
  *
514
483
  * Requires a credential. General authenticated ceiling, 600/min.
515
484
  *
516
- * An empty JSON object is sent as the body. The controller reads nothing from
485
+ * An empty JSON object is sent as the body. The server reads nothing from
517
486
  * it; it is there so the request carries `Content-Type: application/json`
518
487
  * like every other POST in this API rather than arriving bodyless.
519
488
  */
@@ -523,26 +492,22 @@ export declare class PasskeysNamespace extends Resource {
523
492
  * the new {@link Passkey}.
524
493
  *
525
494
  * `input.credential` is posted VERBATIM. Nothing here copies it, reshapes it,
526
- * filters its keys or rewrites a `null` inside it, because the server reads
527
- * it with `params.require(:credential).to_unsafe_h` and hands the raw hash to
528
- * the gem, which then checks a signature over those exact bytes.
495
+ * filters its keys or rewrites a `null` inside it, because the server checks
496
+ * a signature over those exact bytes.
529
497
  *
530
498
  * ## The failure modes, and which of them are honest
531
499
  *
532
- * The controller rescues `WebAuthn::Error` and turns it into a `400`. Some of
533
- * what can go wrong here is NOT a `WebAuthn::Error`, and those reach you as a
534
- * `500`:
500
+ * A verification failure is a `400`. Some of what can go wrong here is not
501
+ * treated as one, and reaches you as a `500`:
535
502
  *
536
503
  * - `type` that is not exactly `"public-key"`, or an `id` and `rawId` whose
537
- * decoded bytes differ: `PublicKeyCredential#verify` calls bare
538
- * `raise("invalid type")` / `raise("invalid id")`, which are `RuntimeError`
539
- * and slip past the rescue;
540
- * - `rawId` absent or `null`: the decoder calls `end_with?` on it and raises
541
- * `NoMethodError`. See {@link normalizePasskeyRegistrationCredential},
504
+ * decoded bytes differ;
505
+ * - `rawId` absent or `null`. See {@link normalizePasskeyRegistrationCredential},
542
506
  * which fills `rawId` from `id` for the Android case where the platform
543
- * really does send `null`;
544
- * - `credential` absent altogether: `params.require` raises
545
- * `ParameterMissing`, which Rails renders as `400`.
507
+ * really does send `null`.
508
+ *
509
+ * `credential` absent altogether is the one malformed shape that is still a
510
+ * `400`.
546
511
  *
547
512
  * So a `500` from this endpoint is a malformed payload, not an outage, and it
548
513
  * is the single most likely thing to be wrong on a client that hand-builds
@@ -561,10 +526,9 @@ export declare class PasskeysNamespace extends Resource {
561
526
  * again."` when more than two minutes passed since
562
527
  * {@link registrationOptions}, or when a second call to it overwrote this
563
528
  * ceremony's challenge.
564
- * @throws {OmsApiError} 400 when verification fails, or when the row will not
565
- * save - which in practice means `external_id` is already taken, i.e. this
566
- * authenticator is already registered and `excludeCredentials` did not stop
567
- * it.
529
+ * @throws {OmsApiError} 400 when verification fails, or when the passkey
530
+ * cannot be stored - which in practice means this authenticator is already
531
+ * registered and `excludeCredentials` did not stop it.
568
532
  */
569
533
  register(input: RegisterPasskeyInput, options?: RequestOptions): Promise<Passkey>;
570
534
  /**
@@ -572,9 +536,9 @@ export declare class PasskeysNamespace extends Resource {
572
536
  * returns the challenge handle plus the arguments for
573
537
  * `navigator.credentials.get()`.
574
538
  *
575
- * **Send this with NO credential.** The route is
576
- * `allow_unauthenticated_access`, and the whole point is that there is no
577
- * session yet. The transport always attaches `Authorization` when the client
539
+ * **Send this with NO credential.** The route accepts anonymous callers,
540
+ * and the whole point is that there is no session yet. The transport always
541
+ * attaches `Authorization` when the client
578
542
  * holds a token, and the caller cannot strip it per request, so a client that
579
543
  * might be signed in should build an anonymous one for the login flow.
580
544
  *
@@ -590,7 +554,7 @@ export declare class PasskeysNamespace extends Resource {
590
554
  *
591
555
  * Retrying is off here, which deviates from the transport's default of
592
556
  * replaying a `429`. The reason is the clock rather than safety: the replay
593
- * sleeps out `Retry-After`, which Rack::Attack sets from a one-minute window,
557
+ * sleeps out `Retry-After`, which the server sets from a one-minute window,
594
558
  * and then hands back a challenge that lives two minutes and still has an OS
595
559
  * sheet and a second rate-limited request ahead of it. Waiting silently
596
560
  * inside the SDK is likelier to produce a login that dies at the last step
@@ -613,16 +577,16 @@ export declare class PasskeysNamespace extends Resource {
613
577
  *
614
578
  * ## An assertion is spent exactly once, so nothing here is replayed
615
579
  *
616
- * The controller deletes the cached challenge BEFORE it verifies anything.
617
- * Once a request has reached the controller the handle is gone whatever the
618
- * outcome, so a second attempt carrying the same body answers `401 "Login
580
+ * The server discards the challenge BEFORE it verifies anything. Once a
581
+ * request has reached it the handle is gone whatever the outcome, so a
582
+ * second attempt carrying the same body answers `401 "Login
619
583
  * challenge expired."` and reports the wrong cause for whatever actually
620
584
  * went wrong.
621
585
  *
622
586
  * The transport's default policy already declines to replay a `POST` after a
623
587
  * torn connection or a `5xx`, which is exactly right for that reason. The one
624
588
  * outcome it WOULD replay is a `429`, and this method turns that off as well.
625
- * A `429` comes from Rack::Attack, ahead of the router, so it genuinely did
589
+ * A `429` is answered before the request is performed, so it genuinely did
626
590
  * not spend the handle; but `Retry-After` is set from a one-minute window,
627
591
  * the challenge lives two minutes, and the OS sheet has already eaten part of
628
592
  * that. Sleeping through the rate limit inside the SDK converts it into an
@@ -642,10 +606,10 @@ export declare class PasskeysNamespace extends Resource {
642
606
  * server has never seen (`"Unknown passkey."`); a deactivated account
643
607
  * (`"This account is deactivated."`); a failed signature, wrong origin or
644
608
  * wrong challenge (`"Passkey could not be verified."`); and a sign counter
645
- * that did not advance, which the gem treats as a cloned authenticator and
646
- * which reports as that same message. Note that passkeys synced through a
647
- * keychain report a counter of `0` forever, and `valid_sign_count?` lets
648
- * `0` against `0` through, so that last case does not fire for them.
609
+ * that did not advance, which the server treats as a cloned authenticator
610
+ * and reports as that same message. Note that passkeys synced through a
611
+ * keychain report a counter of `0` forever, and `0` against `0` is let
612
+ * through, so that last case does not fire for them.
649
613
  * @throws {OmsQuotaError} 429 when the shared per-IP bucket is spent.
650
614
  */
651
615
  authenticate(input: AuthenticatePasskeyInput, options?: RequestOptions): Promise<PasskeySession>;