vaultkeeper 0.3.0 → 0.5.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.
package/dist/index.d.cts CHANGED
@@ -134,6 +134,21 @@ declare class IdentityMismatchError extends VaultError {
134
134
  readonly currentHash: string;
135
135
  constructor(message: string, previousHash: string, currentHash: string);
136
136
  }
137
+ /**
138
+ * Thrown when a caller requests a signing/verification algorithm that is not
139
+ * in the allowed set (e.g. `'md5'`).
140
+ */
141
+ declare class InvalidAlgorithmError extends VaultError {
142
+ /**
143
+ * The algorithm that was requested.
144
+ */
145
+ readonly algorithm: string;
146
+ /**
147
+ * The set of algorithms that are allowed.
148
+ */
149
+ readonly allowed: string[];
150
+ constructor(message: string, algorithm: string, allowed: string[]);
151
+ }
137
152
  /**
138
153
  * Thrown during initialization when a required system dependency (e.g. OpenSSL
139
154
  * or a native credential helper) is missing or incompatible.
@@ -287,6 +302,59 @@ interface SecretAccessor {
287
302
  */
288
303
  read(callback: (buf: Buffer) => void): void;
289
304
  }
305
+ /**
306
+ * Request for delegated signing.
307
+ *
308
+ * The `data` field is the payload to sign. Strings are UTF-8-encoded
309
+ * before signing.
310
+ */
311
+ interface SignRequest {
312
+ /** The data to sign. Strings are treated as UTF-8. */
313
+ data: string | Buffer;
314
+ /**
315
+ * Override the hash algorithm (`'sha256'`, `'sha384'`, or `'sha512'`).
316
+ * Ignored for Ed25519/Ed448 keys where the algorithm is implicit.
317
+ * Non-Edwards keys (RSA, EC) default to `'sha256'` when omitted.
318
+ * Weak algorithms (e.g. `'md5'`, `'sha1'`) are rejected.
319
+ */
320
+ algorithm?: string | undefined;
321
+ }
322
+ /** Result from a delegated signing operation. */
323
+ interface SignResult {
324
+ /** Base64-encoded signature. */
325
+ signature: string;
326
+ /**
327
+ * Algorithm label describing how the signature was produced.
328
+ * For Edwards keys this is the key type (e.g. `'ed25519'`).
329
+ * For other keys this matches the `algorithm` field from the request
330
+ * (or the default `'sha256'`).
331
+ */
332
+ algorithm: string;
333
+ }
334
+ /**
335
+ * Request for signature verification.
336
+ *
337
+ * This is a static operation that only requires public key material —
338
+ * no VaultKeeper instance or capability token is needed.
339
+ */
340
+ interface VerifyRequest {
341
+ /** The original data that was signed. Strings are treated as UTF-8. */
342
+ data: string | Buffer;
343
+ /** Base64-encoded signature to verify. */
344
+ signature: string;
345
+ /**
346
+ * PEM-encoded public key (SPKI format) as a string.
347
+ *
348
+ * Other `KeyLike` formats supported by `crypto.createPublicKey()` are not
349
+ * accepted by this interface.
350
+ */
351
+ publicKey: string;
352
+ /**
353
+ * Override the hash algorithm. Ignored for Ed25519/Ed448 keys.
354
+ * Non-Edwards keys default to `'sha256'` when omitted.
355
+ */
356
+ algorithm?: string | undefined;
357
+ }
290
358
  /** Vaultkeeper configuration file structure. */
291
359
  interface VaultConfig {
292
360
  /** Config schema version. Currently must be `1`. */
@@ -324,6 +392,8 @@ interface BackendConfig {
324
392
  plugin?: boolean | undefined;
325
393
  /** Filesystem path used by file-based backends. */
326
394
  path?: string | undefined;
395
+ /** Backend-specific options collected during interactive setup. */
396
+ options?: Record<string, string> | undefined;
327
397
  }
328
398
 
329
399
  /**
@@ -331,9 +401,15 @@ interface BackendConfig {
331
401
  */
332
402
  /**
333
403
  * Factory function for creating a SecretBackend instance.
404
+ *
405
+ * @remarks
406
+ * Factories may optionally accept a {@link BackendConfig} to configure the
407
+ * backend from the user's vaultkeeper config file. Factories that do not need
408
+ * configuration can ignore the parameter.
409
+ *
334
410
  * @public
335
411
  */
336
- type BackendFactory = () => SecretBackend;
412
+ type BackendFactory = (config?: BackendConfig) => SecretBackend;
337
413
  /**
338
414
  * Abstraction interface for all secret storage backends.
339
415
  *
@@ -397,12 +473,45 @@ interface ListableBackend extends SecretBackend {
397
473
  declare function isListableBackend(backend: SecretBackend): backend is ListableBackend;
398
474
 
399
475
  /**
400
- * Registry for secret backend implementations.
476
+ * Types for the backend setup protocol.
401
477
  *
402
- * @remarks
403
- * The registry maintains a mapping of backend types to factory functions,
404
- * allowing dynamic creation of backends based on configuration.
478
+ * @packageDocumentation
479
+ */
480
+ /**
481
+ * A question yielded by a backend setup generator.
482
+ * @public
483
+ */
484
+ interface SetupQuestion {
485
+ /** Machine key for BackendConfig.options */
486
+ readonly key: string;
487
+ /** Human-readable prompt */
488
+ readonly prompt: string;
489
+ /** Present for selection questions; when absent, the answer is a free-form string. */
490
+ readonly choices?: readonly SetupChoice[];
491
+ }
492
+ /**
493
+ * A choice within a setup question.
494
+ * @public
495
+ */
496
+ interface SetupChoice {
497
+ /** Persisted value */
498
+ readonly value: string;
499
+ /** Display label */
500
+ readonly label: string;
501
+ }
502
+ /**
503
+ * Result returned when a backend setup generator completes.
504
+ * @public
505
+ */
506
+ interface SetupResult {
507
+ /** Merge into BackendConfig.options */
508
+ readonly options: Record<string, string>;
509
+ }
510
+ /**
511
+ * Factory that creates a backend setup generator.
512
+ * @public
405
513
  */
514
+ type BackendSetupFactory = () => AsyncGenerator<SetupQuestion, SetupResult, string>;
406
515
 
407
516
  /**
408
517
  * Registry for secret backend implementations.
@@ -416,6 +525,7 @@ declare function isListableBackend(backend: SecretBackend): backend is ListableB
416
525
  */
417
526
  declare class BackendRegistry {
418
527
  private static backends;
528
+ private static setups;
419
529
  /**
420
530
  * Register a backend factory.
421
531
  * @param type - Backend type identifier
@@ -425,10 +535,11 @@ declare class BackendRegistry {
425
535
  /**
426
536
  * Create a backend instance by type.
427
537
  * @param type - Backend type identifier
538
+ * @param config - Optional backend configuration forwarded to the factory
428
539
  * @returns A SecretBackend instance
429
- * @throws Error if the backend type is not registered
540
+ * @throws {@link BackendUnavailableError} if the backend type is not registered
430
541
  */
431
- static create(type: string): SecretBackend;
542
+ static create(type: string, config?: BackendConfig): SecretBackend;
432
543
  /**
433
544
  * Get all registered backend type identifiers.
434
545
  * @returns Array of backend type identifiers
@@ -447,6 +558,36 @@ declare class BackendRegistry {
447
558
  * @public
448
559
  */
449
560
  static getAvailableTypes(): Promise<string[]>;
561
+ /**
562
+ * Register a setup factory for a backend type.
563
+ * @param type - Backend type identifier
564
+ * @param factory - Factory function that creates a setup generator
565
+ */
566
+ static registerSetup(type: string, factory: BackendSetupFactory): void;
567
+ /**
568
+ * Get the setup factory for a backend type, if one is registered.
569
+ * @param type - Backend type identifier
570
+ * @returns The setup factory, or `undefined` if none is registered
571
+ */
572
+ static getSetup(type: string): BackendSetupFactory | undefined;
573
+ /**
574
+ * Check whether a setup factory is registered for the given backend type.
575
+ * @param type - Backend type identifier
576
+ * @returns `true` if a setup factory is registered
577
+ */
578
+ static hasSetup(type: string): boolean;
579
+ /**
580
+ * Clear all registered backend factories.
581
+ * Intended for use in tests only.
582
+ * @internal
583
+ */
584
+ static clearBackends(): void;
585
+ /**
586
+ * Clear all registered setup factories.
587
+ * Intended for use in tests only.
588
+ * @internal
589
+ */
590
+ static clearSetups(): void;
450
591
  }
451
592
 
452
593
  /**
@@ -578,6 +719,45 @@ declare class VaultKeeper {
578
719
  * instance.
579
720
  */
580
721
  getSecret(token: CapabilityToken): SecretAccessor;
722
+ /**
723
+ * Sign data using the private key embedded in a capability token.
724
+ *
725
+ * The signing key is extracted from the token's encrypted claims, used
726
+ * for a single `crypto.sign()` call, and never exposed to the caller.
727
+ * The algorithm is auto-detected from the key type unless overridden
728
+ * in the request.
729
+ *
730
+ * @param token - A `CapabilityToken` obtained from `authorize()`.
731
+ * @param request - The data to sign and optional algorithm override.
732
+ * @returns The base64-encoded signature and algorithm label, together
733
+ * with the vault metadata (`vaultResponse`).
734
+ * @throws {VaultError} If `token` is invalid or was not created by this
735
+ * vault instance.
736
+ * @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
737
+ * allowed set (e.g. `'md5'`).
738
+ */
739
+ sign(token: CapabilityToken, request: SignRequest): Promise<{
740
+ result: SignResult;
741
+ vaultResponse: VaultResponse;
742
+ }>;
743
+ /**
744
+ * Verify a signature using a public key.
745
+ *
746
+ * This is a static method — no VaultKeeper instance, secrets, or
747
+ * capability tokens are required. It is safe to call from CI or any
748
+ * context that has access to public key material.
749
+ *
750
+ * Returns `false` for invalid key material, malformed signatures, or
751
+ * any verification failure (except disallowed algorithms, which throw).
752
+ *
753
+ * @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
754
+ * allowed set (e.g. `'md5'`).
755
+ *
756
+ * @param request - The data, signature, public key, and optional
757
+ * algorithm override.
758
+ * @returns `true` if the signature is valid, `false` otherwise.
759
+ */
760
+ static verify(request: VerifyRequest): boolean;
581
761
  /**
582
762
  * Rotate the current encryption key.
583
763
  *
@@ -613,4 +793,4 @@ declare class VaultKeeper {
613
793
  setDevelopmentMode(executablePath: string, enabled: boolean): Promise<void>;
614
794
  }
615
795
 
616
- export { AuthorizationDeniedError, type BackendConfig, type BackendFactory, BackendLockedError, BackendRegistry, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, type ExecRequest, type ExecResult, type FetchRequest, FilesystemError, IdentityMismatchError, KeyRevokedError, KeyRotatedError, type KeyStatus, type ListableBackend, PluginNotFoundError, type PreflightCheck, type PreflightCheckStatus, type PreflightResult, RotationInProgressError, type SecretAccessor, type SecretBackend, SecretNotFoundError, SetupError, type SetupOptions, TokenExpiredError, TokenRevokedError, type TrustTier, UsageLimitExceededError, type VaultConfig, VaultError, VaultKeeper, type VaultKeeperOptions, type VaultResponse, isListableBackend };
796
+ export { AuthorizationDeniedError, type BackendConfig, type BackendFactory, BackendLockedError, BackendRegistry, type BackendSetupFactory, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, type ExecRequest, type ExecResult, type FetchRequest, FilesystemError, IdentityMismatchError, InvalidAlgorithmError, KeyRevokedError, KeyRotatedError, type KeyStatus, type ListableBackend, PluginNotFoundError, type PreflightCheck, type PreflightCheckStatus, type PreflightResult, RotationInProgressError, type SecretAccessor, type SecretBackend, SecretNotFoundError, type SetupChoice, SetupError, type SetupOptions, type SetupQuestion, type SetupResult, type SignRequest, type SignResult, TokenExpiredError, TokenRevokedError, type TrustTier, UsageLimitExceededError, type VaultConfig, VaultError, VaultKeeper, type VaultKeeperOptions, type VaultResponse, type VerifyRequest, isListableBackend };
package/dist/index.d.ts CHANGED
@@ -134,6 +134,21 @@ declare class IdentityMismatchError extends VaultError {
134
134
  readonly currentHash: string;
135
135
  constructor(message: string, previousHash: string, currentHash: string);
136
136
  }
137
+ /**
138
+ * Thrown when a caller requests a signing/verification algorithm that is not
139
+ * in the allowed set (e.g. `'md5'`).
140
+ */
141
+ declare class InvalidAlgorithmError extends VaultError {
142
+ /**
143
+ * The algorithm that was requested.
144
+ */
145
+ readonly algorithm: string;
146
+ /**
147
+ * The set of algorithms that are allowed.
148
+ */
149
+ readonly allowed: string[];
150
+ constructor(message: string, algorithm: string, allowed: string[]);
151
+ }
137
152
  /**
138
153
  * Thrown during initialization when a required system dependency (e.g. OpenSSL
139
154
  * or a native credential helper) is missing or incompatible.
@@ -287,6 +302,59 @@ interface SecretAccessor {
287
302
  */
288
303
  read(callback: (buf: Buffer) => void): void;
289
304
  }
305
+ /**
306
+ * Request for delegated signing.
307
+ *
308
+ * The `data` field is the payload to sign. Strings are UTF-8-encoded
309
+ * before signing.
310
+ */
311
+ interface SignRequest {
312
+ /** The data to sign. Strings are treated as UTF-8. */
313
+ data: string | Buffer;
314
+ /**
315
+ * Override the hash algorithm (`'sha256'`, `'sha384'`, or `'sha512'`).
316
+ * Ignored for Ed25519/Ed448 keys where the algorithm is implicit.
317
+ * Non-Edwards keys (RSA, EC) default to `'sha256'` when omitted.
318
+ * Weak algorithms (e.g. `'md5'`, `'sha1'`) are rejected.
319
+ */
320
+ algorithm?: string | undefined;
321
+ }
322
+ /** Result from a delegated signing operation. */
323
+ interface SignResult {
324
+ /** Base64-encoded signature. */
325
+ signature: string;
326
+ /**
327
+ * Algorithm label describing how the signature was produced.
328
+ * For Edwards keys this is the key type (e.g. `'ed25519'`).
329
+ * For other keys this matches the `algorithm` field from the request
330
+ * (or the default `'sha256'`).
331
+ */
332
+ algorithm: string;
333
+ }
334
+ /**
335
+ * Request for signature verification.
336
+ *
337
+ * This is a static operation that only requires public key material —
338
+ * no VaultKeeper instance or capability token is needed.
339
+ */
340
+ interface VerifyRequest {
341
+ /** The original data that was signed. Strings are treated as UTF-8. */
342
+ data: string | Buffer;
343
+ /** Base64-encoded signature to verify. */
344
+ signature: string;
345
+ /**
346
+ * PEM-encoded public key (SPKI format) as a string.
347
+ *
348
+ * Other `KeyLike` formats supported by `crypto.createPublicKey()` are not
349
+ * accepted by this interface.
350
+ */
351
+ publicKey: string;
352
+ /**
353
+ * Override the hash algorithm. Ignored for Ed25519/Ed448 keys.
354
+ * Non-Edwards keys default to `'sha256'` when omitted.
355
+ */
356
+ algorithm?: string | undefined;
357
+ }
290
358
  /** Vaultkeeper configuration file structure. */
291
359
  interface VaultConfig {
292
360
  /** Config schema version. Currently must be `1`. */
@@ -324,6 +392,8 @@ interface BackendConfig {
324
392
  plugin?: boolean | undefined;
325
393
  /** Filesystem path used by file-based backends. */
326
394
  path?: string | undefined;
395
+ /** Backend-specific options collected during interactive setup. */
396
+ options?: Record<string, string> | undefined;
327
397
  }
328
398
 
329
399
  /**
@@ -331,9 +401,15 @@ interface BackendConfig {
331
401
  */
332
402
  /**
333
403
  * Factory function for creating a SecretBackend instance.
404
+ *
405
+ * @remarks
406
+ * Factories may optionally accept a {@link BackendConfig} to configure the
407
+ * backend from the user's vaultkeeper config file. Factories that do not need
408
+ * configuration can ignore the parameter.
409
+ *
334
410
  * @public
335
411
  */
336
- type BackendFactory = () => SecretBackend;
412
+ type BackendFactory = (config?: BackendConfig) => SecretBackend;
337
413
  /**
338
414
  * Abstraction interface for all secret storage backends.
339
415
  *
@@ -397,12 +473,45 @@ interface ListableBackend extends SecretBackend {
397
473
  declare function isListableBackend(backend: SecretBackend): backend is ListableBackend;
398
474
 
399
475
  /**
400
- * Registry for secret backend implementations.
476
+ * Types for the backend setup protocol.
401
477
  *
402
- * @remarks
403
- * The registry maintains a mapping of backend types to factory functions,
404
- * allowing dynamic creation of backends based on configuration.
478
+ * @packageDocumentation
479
+ */
480
+ /**
481
+ * A question yielded by a backend setup generator.
482
+ * @public
483
+ */
484
+ interface SetupQuestion {
485
+ /** Machine key for BackendConfig.options */
486
+ readonly key: string;
487
+ /** Human-readable prompt */
488
+ readonly prompt: string;
489
+ /** Present for selection questions; when absent, the answer is a free-form string. */
490
+ readonly choices?: readonly SetupChoice[];
491
+ }
492
+ /**
493
+ * A choice within a setup question.
494
+ * @public
495
+ */
496
+ interface SetupChoice {
497
+ /** Persisted value */
498
+ readonly value: string;
499
+ /** Display label */
500
+ readonly label: string;
501
+ }
502
+ /**
503
+ * Result returned when a backend setup generator completes.
504
+ * @public
505
+ */
506
+ interface SetupResult {
507
+ /** Merge into BackendConfig.options */
508
+ readonly options: Record<string, string>;
509
+ }
510
+ /**
511
+ * Factory that creates a backend setup generator.
512
+ * @public
405
513
  */
514
+ type BackendSetupFactory = () => AsyncGenerator<SetupQuestion, SetupResult, string>;
406
515
 
407
516
  /**
408
517
  * Registry for secret backend implementations.
@@ -416,6 +525,7 @@ declare function isListableBackend(backend: SecretBackend): backend is ListableB
416
525
  */
417
526
  declare class BackendRegistry {
418
527
  private static backends;
528
+ private static setups;
419
529
  /**
420
530
  * Register a backend factory.
421
531
  * @param type - Backend type identifier
@@ -425,10 +535,11 @@ declare class BackendRegistry {
425
535
  /**
426
536
  * Create a backend instance by type.
427
537
  * @param type - Backend type identifier
538
+ * @param config - Optional backend configuration forwarded to the factory
428
539
  * @returns A SecretBackend instance
429
- * @throws Error if the backend type is not registered
540
+ * @throws {@link BackendUnavailableError} if the backend type is not registered
430
541
  */
431
- static create(type: string): SecretBackend;
542
+ static create(type: string, config?: BackendConfig): SecretBackend;
432
543
  /**
433
544
  * Get all registered backend type identifiers.
434
545
  * @returns Array of backend type identifiers
@@ -447,6 +558,36 @@ declare class BackendRegistry {
447
558
  * @public
448
559
  */
449
560
  static getAvailableTypes(): Promise<string[]>;
561
+ /**
562
+ * Register a setup factory for a backend type.
563
+ * @param type - Backend type identifier
564
+ * @param factory - Factory function that creates a setup generator
565
+ */
566
+ static registerSetup(type: string, factory: BackendSetupFactory): void;
567
+ /**
568
+ * Get the setup factory for a backend type, if one is registered.
569
+ * @param type - Backend type identifier
570
+ * @returns The setup factory, or `undefined` if none is registered
571
+ */
572
+ static getSetup(type: string): BackendSetupFactory | undefined;
573
+ /**
574
+ * Check whether a setup factory is registered for the given backend type.
575
+ * @param type - Backend type identifier
576
+ * @returns `true` if a setup factory is registered
577
+ */
578
+ static hasSetup(type: string): boolean;
579
+ /**
580
+ * Clear all registered backend factories.
581
+ * Intended for use in tests only.
582
+ * @internal
583
+ */
584
+ static clearBackends(): void;
585
+ /**
586
+ * Clear all registered setup factories.
587
+ * Intended for use in tests only.
588
+ * @internal
589
+ */
590
+ static clearSetups(): void;
450
591
  }
451
592
 
452
593
  /**
@@ -578,6 +719,45 @@ declare class VaultKeeper {
578
719
  * instance.
579
720
  */
580
721
  getSecret(token: CapabilityToken): SecretAccessor;
722
+ /**
723
+ * Sign data using the private key embedded in a capability token.
724
+ *
725
+ * The signing key is extracted from the token's encrypted claims, used
726
+ * for a single `crypto.sign()` call, and never exposed to the caller.
727
+ * The algorithm is auto-detected from the key type unless overridden
728
+ * in the request.
729
+ *
730
+ * @param token - A `CapabilityToken` obtained from `authorize()`.
731
+ * @param request - The data to sign and optional algorithm override.
732
+ * @returns The base64-encoded signature and algorithm label, together
733
+ * with the vault metadata (`vaultResponse`).
734
+ * @throws {VaultError} If `token` is invalid or was not created by this
735
+ * vault instance.
736
+ * @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
737
+ * allowed set (e.g. `'md5'`).
738
+ */
739
+ sign(token: CapabilityToken, request: SignRequest): Promise<{
740
+ result: SignResult;
741
+ vaultResponse: VaultResponse;
742
+ }>;
743
+ /**
744
+ * Verify a signature using a public key.
745
+ *
746
+ * This is a static method — no VaultKeeper instance, secrets, or
747
+ * capability tokens are required. It is safe to call from CI or any
748
+ * context that has access to public key material.
749
+ *
750
+ * Returns `false` for invalid key material, malformed signatures, or
751
+ * any verification failure (except disallowed algorithms, which throw).
752
+ *
753
+ * @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
754
+ * allowed set (e.g. `'md5'`).
755
+ *
756
+ * @param request - The data, signature, public key, and optional
757
+ * algorithm override.
758
+ * @returns `true` if the signature is valid, `false` otherwise.
759
+ */
760
+ static verify(request: VerifyRequest): boolean;
581
761
  /**
582
762
  * Rotate the current encryption key.
583
763
  *
@@ -613,4 +793,4 @@ declare class VaultKeeper {
613
793
  setDevelopmentMode(executablePath: string, enabled: boolean): Promise<void>;
614
794
  }
615
795
 
616
- export { AuthorizationDeniedError, type BackendConfig, type BackendFactory, BackendLockedError, BackendRegistry, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, type ExecRequest, type ExecResult, type FetchRequest, FilesystemError, IdentityMismatchError, KeyRevokedError, KeyRotatedError, type KeyStatus, type ListableBackend, PluginNotFoundError, type PreflightCheck, type PreflightCheckStatus, type PreflightResult, RotationInProgressError, type SecretAccessor, type SecretBackend, SecretNotFoundError, SetupError, type SetupOptions, TokenExpiredError, TokenRevokedError, type TrustTier, UsageLimitExceededError, type VaultConfig, VaultError, VaultKeeper, type VaultKeeperOptions, type VaultResponse, isListableBackend };
796
+ export { AuthorizationDeniedError, type BackendConfig, type BackendFactory, BackendLockedError, BackendRegistry, type BackendSetupFactory, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, type ExecRequest, type ExecResult, type FetchRequest, FilesystemError, IdentityMismatchError, InvalidAlgorithmError, KeyRevokedError, KeyRotatedError, type KeyStatus, type ListableBackend, PluginNotFoundError, type PreflightCheck, type PreflightCheckStatus, type PreflightResult, RotationInProgressError, type SecretAccessor, type SecretBackend, SecretNotFoundError, type SetupChoice, SetupError, type SetupOptions, type SetupQuestion, type SetupResult, type SignRequest, type SignResult, TokenExpiredError, TokenRevokedError, type TrustTier, UsageLimitExceededError, type VaultConfig, VaultError, VaultKeeper, type VaultKeeperOptions, type VaultResponse, type VerifyRequest, isListableBackend };