vaultkeeper 0.3.0 → 1.0.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
  /**
@@ -396,6 +466,47 @@ interface ListableBackend extends SecretBackend {
396
466
  */
397
467
  declare function isListableBackend(backend: SecretBackend): backend is ListableBackend;
398
468
 
469
+ /**
470
+ * Types for the backend setup protocol.
471
+ *
472
+ * @packageDocumentation
473
+ */
474
+ /**
475
+ * A question yielded by a backend setup generator.
476
+ * @public
477
+ */
478
+ interface SetupQuestion {
479
+ /** Machine key for BackendConfig.options */
480
+ readonly key: string;
481
+ /** Human-readable prompt */
482
+ readonly prompt: string;
483
+ /** Present for selection questions; when absent, the answer is a free-form string. */
484
+ readonly choices?: readonly SetupChoice[];
485
+ }
486
+ /**
487
+ * A choice within a setup question.
488
+ * @public
489
+ */
490
+ interface SetupChoice {
491
+ /** Persisted value */
492
+ readonly value: string;
493
+ /** Display label */
494
+ readonly label: string;
495
+ }
496
+ /**
497
+ * Result returned when a backend setup generator completes.
498
+ * @public
499
+ */
500
+ interface SetupResult {
501
+ /** Merge into BackendConfig.options */
502
+ readonly options: Record<string, string>;
503
+ }
504
+ /**
505
+ * Factory that creates a backend setup generator.
506
+ * @public
507
+ */
508
+ type BackendSetupFactory = () => AsyncGenerator<SetupQuestion, SetupResult, string>;
509
+
399
510
  /**
400
511
  * Registry for secret backend implementations.
401
512
  *
@@ -416,6 +527,7 @@ declare function isListableBackend(backend: SecretBackend): backend is ListableB
416
527
  */
417
528
  declare class BackendRegistry {
418
529
  private static backends;
530
+ private static setups;
419
531
  /**
420
532
  * Register a backend factory.
421
533
  * @param type - Backend type identifier
@@ -426,7 +538,7 @@ declare class BackendRegistry {
426
538
  * Create a backend instance by type.
427
539
  * @param type - Backend type identifier
428
540
  * @returns A SecretBackend instance
429
- * @throws Error if the backend type is not registered
541
+ * @throws {@link BackendUnavailableError} if the backend type is not registered
430
542
  */
431
543
  static create(type: string): SecretBackend;
432
544
  /**
@@ -447,6 +559,36 @@ declare class BackendRegistry {
447
559
  * @public
448
560
  */
449
561
  static getAvailableTypes(): Promise<string[]>;
562
+ /**
563
+ * Register a setup factory for a backend type.
564
+ * @param type - Backend type identifier
565
+ * @param factory - Factory function that creates a setup generator
566
+ */
567
+ static registerSetup(type: string, factory: BackendSetupFactory): void;
568
+ /**
569
+ * Get the setup factory for a backend type, if one is registered.
570
+ * @param type - Backend type identifier
571
+ * @returns The setup factory, or `undefined` if none is registered
572
+ */
573
+ static getSetup(type: string): BackendSetupFactory | undefined;
574
+ /**
575
+ * Check whether a setup factory is registered for the given backend type.
576
+ * @param type - Backend type identifier
577
+ * @returns `true` if a setup factory is registered
578
+ */
579
+ static hasSetup(type: string): boolean;
580
+ /**
581
+ * Clear all registered backend factories.
582
+ * Intended for use in tests only.
583
+ * @internal
584
+ */
585
+ static clearBackends(): void;
586
+ /**
587
+ * Clear all registered setup factories.
588
+ * Intended for use in tests only.
589
+ * @internal
590
+ */
591
+ static clearSetups(): void;
450
592
  }
451
593
 
452
594
  /**
@@ -578,6 +720,45 @@ declare class VaultKeeper {
578
720
  * instance.
579
721
  */
580
722
  getSecret(token: CapabilityToken): SecretAccessor;
723
+ /**
724
+ * Sign data using the private key embedded in a capability token.
725
+ *
726
+ * The signing key is extracted from the token's encrypted claims, used
727
+ * for a single `crypto.sign()` call, and never exposed to the caller.
728
+ * The algorithm is auto-detected from the key type unless overridden
729
+ * in the request.
730
+ *
731
+ * @param token - A `CapabilityToken` obtained from `authorize()`.
732
+ * @param request - The data to sign and optional algorithm override.
733
+ * @returns The base64-encoded signature and algorithm label, together
734
+ * with the vault metadata (`vaultResponse`).
735
+ * @throws {VaultError} If `token` is invalid or was not created by this
736
+ * vault instance.
737
+ * @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
738
+ * allowed set (e.g. `'md5'`).
739
+ */
740
+ sign(token: CapabilityToken, request: SignRequest): Promise<{
741
+ result: SignResult;
742
+ vaultResponse: VaultResponse;
743
+ }>;
744
+ /**
745
+ * Verify a signature using a public key.
746
+ *
747
+ * This is a static method — no VaultKeeper instance, secrets, or
748
+ * capability tokens are required. It is safe to call from CI or any
749
+ * context that has access to public key material.
750
+ *
751
+ * Returns `false` for invalid key material, malformed signatures, or
752
+ * any verification failure (except disallowed algorithms, which throw).
753
+ *
754
+ * @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
755
+ * allowed set (e.g. `'md5'`).
756
+ *
757
+ * @param request - The data, signature, public key, and optional
758
+ * algorithm override.
759
+ * @returns `true` if the signature is valid, `false` otherwise.
760
+ */
761
+ static verify(request: VerifyRequest): boolean;
581
762
  /**
582
763
  * Rotate the current encryption key.
583
764
  *
@@ -613,4 +794,4 @@ declare class VaultKeeper {
613
794
  setDevelopmentMode(executablePath: string, enabled: boolean): Promise<void>;
614
795
  }
615
796
 
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 };
797
+ 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
  /**
@@ -396,6 +466,47 @@ interface ListableBackend extends SecretBackend {
396
466
  */
397
467
  declare function isListableBackend(backend: SecretBackend): backend is ListableBackend;
398
468
 
469
+ /**
470
+ * Types for the backend setup protocol.
471
+ *
472
+ * @packageDocumentation
473
+ */
474
+ /**
475
+ * A question yielded by a backend setup generator.
476
+ * @public
477
+ */
478
+ interface SetupQuestion {
479
+ /** Machine key for BackendConfig.options */
480
+ readonly key: string;
481
+ /** Human-readable prompt */
482
+ readonly prompt: string;
483
+ /** Present for selection questions; when absent, the answer is a free-form string. */
484
+ readonly choices?: readonly SetupChoice[];
485
+ }
486
+ /**
487
+ * A choice within a setup question.
488
+ * @public
489
+ */
490
+ interface SetupChoice {
491
+ /** Persisted value */
492
+ readonly value: string;
493
+ /** Display label */
494
+ readonly label: string;
495
+ }
496
+ /**
497
+ * Result returned when a backend setup generator completes.
498
+ * @public
499
+ */
500
+ interface SetupResult {
501
+ /** Merge into BackendConfig.options */
502
+ readonly options: Record<string, string>;
503
+ }
504
+ /**
505
+ * Factory that creates a backend setup generator.
506
+ * @public
507
+ */
508
+ type BackendSetupFactory = () => AsyncGenerator<SetupQuestion, SetupResult, string>;
509
+
399
510
  /**
400
511
  * Registry for secret backend implementations.
401
512
  *
@@ -416,6 +527,7 @@ declare function isListableBackend(backend: SecretBackend): backend is ListableB
416
527
  */
417
528
  declare class BackendRegistry {
418
529
  private static backends;
530
+ private static setups;
419
531
  /**
420
532
  * Register a backend factory.
421
533
  * @param type - Backend type identifier
@@ -426,7 +538,7 @@ declare class BackendRegistry {
426
538
  * Create a backend instance by type.
427
539
  * @param type - Backend type identifier
428
540
  * @returns A SecretBackend instance
429
- * @throws Error if the backend type is not registered
541
+ * @throws {@link BackendUnavailableError} if the backend type is not registered
430
542
  */
431
543
  static create(type: string): SecretBackend;
432
544
  /**
@@ -447,6 +559,36 @@ declare class BackendRegistry {
447
559
  * @public
448
560
  */
449
561
  static getAvailableTypes(): Promise<string[]>;
562
+ /**
563
+ * Register a setup factory for a backend type.
564
+ * @param type - Backend type identifier
565
+ * @param factory - Factory function that creates a setup generator
566
+ */
567
+ static registerSetup(type: string, factory: BackendSetupFactory): void;
568
+ /**
569
+ * Get the setup factory for a backend type, if one is registered.
570
+ * @param type - Backend type identifier
571
+ * @returns The setup factory, or `undefined` if none is registered
572
+ */
573
+ static getSetup(type: string): BackendSetupFactory | undefined;
574
+ /**
575
+ * Check whether a setup factory is registered for the given backend type.
576
+ * @param type - Backend type identifier
577
+ * @returns `true` if a setup factory is registered
578
+ */
579
+ static hasSetup(type: string): boolean;
580
+ /**
581
+ * Clear all registered backend factories.
582
+ * Intended for use in tests only.
583
+ * @internal
584
+ */
585
+ static clearBackends(): void;
586
+ /**
587
+ * Clear all registered setup factories.
588
+ * Intended for use in tests only.
589
+ * @internal
590
+ */
591
+ static clearSetups(): void;
450
592
  }
451
593
 
452
594
  /**
@@ -578,6 +720,45 @@ declare class VaultKeeper {
578
720
  * instance.
579
721
  */
580
722
  getSecret(token: CapabilityToken): SecretAccessor;
723
+ /**
724
+ * Sign data using the private key embedded in a capability token.
725
+ *
726
+ * The signing key is extracted from the token's encrypted claims, used
727
+ * for a single `crypto.sign()` call, and never exposed to the caller.
728
+ * The algorithm is auto-detected from the key type unless overridden
729
+ * in the request.
730
+ *
731
+ * @param token - A `CapabilityToken` obtained from `authorize()`.
732
+ * @param request - The data to sign and optional algorithm override.
733
+ * @returns The base64-encoded signature and algorithm label, together
734
+ * with the vault metadata (`vaultResponse`).
735
+ * @throws {VaultError} If `token` is invalid or was not created by this
736
+ * vault instance.
737
+ * @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
738
+ * allowed set (e.g. `'md5'`).
739
+ */
740
+ sign(token: CapabilityToken, request: SignRequest): Promise<{
741
+ result: SignResult;
742
+ vaultResponse: VaultResponse;
743
+ }>;
744
+ /**
745
+ * Verify a signature using a public key.
746
+ *
747
+ * This is a static method — no VaultKeeper instance, secrets, or
748
+ * capability tokens are required. It is safe to call from CI or any
749
+ * context that has access to public key material.
750
+ *
751
+ * Returns `false` for invalid key material, malformed signatures, or
752
+ * any verification failure (except disallowed algorithms, which throw).
753
+ *
754
+ * @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
755
+ * allowed set (e.g. `'md5'`).
756
+ *
757
+ * @param request - The data, signature, public key, and optional
758
+ * algorithm override.
759
+ * @returns `true` if the signature is valid, `false` otherwise.
760
+ */
761
+ static verify(request: VerifyRequest): boolean;
581
762
  /**
582
763
  * Rotate the current encryption key.
583
764
  *
@@ -613,4 +794,4 @@ declare class VaultKeeper {
613
794
  setDevelopmentMode(executablePath: string, enabled: boolean): Promise<void>;
614
795
  }
615
796
 
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 };
797
+ 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 };