first commit
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# CryptoVaultError
|
||||
|
||||
## Purpose
|
||||
|
||||
`CryptoVaultError` is the umbrella error class for `@suaveplan/crypto-vault`.
|
||||
Every failure mode in the package — invalid BIP39 entropy, unsafe Argon2id
|
||||
parameters, SRP authentication failures, zeroized SecureBuffer access — is
|
||||
surfaced as a `CryptoVaultError` carrying a code from
|
||||
`CRYPTO_VAULT_CODES`. Extending `SuaveplanError` means the error participates
|
||||
in the project's wire format, OTel span events, redaction, and i18n
|
||||
infrastructure for free.
|
||||
|
||||
## Features
|
||||
|
||||
- Inherits structured `code`, `context`, `timestamp`, and `traceId` from
|
||||
`SuaveplanError`.
|
||||
- Code field is narrowed to the `CryptoVaultCode` union so `switch (err.code)`
|
||||
is exhaustive.
|
||||
- Tagged with a unique brand symbol so cross-realm `instanceof` checks (web
|
||||
workers, iframes) can be defended against via `CryptoVaultError.is(value)`.
|
||||
- Public constructor — internal modules instantiate freely; consumers may
|
||||
also instantiate when re-throwing across boundaries.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
CRYPTO_VAULT_CODES,
|
||||
CryptoVaultError,
|
||||
} from "@suaveplan/crypto-vault/errors";
|
||||
|
||||
throw new CryptoVaultError(
|
||||
CRYPTO_VAULT_CODES["BIP39.INVALID_MNEMONIC"],
|
||||
"error.crypto-vault.bip39.invalid-mnemonic"
|
||||
);
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
CRYPTO_VAULT_CODES,
|
||||
CryptoVaultError,
|
||||
} from "@suaveplan/crypto-vault/errors";
|
||||
|
||||
try {
|
||||
// ... call into crypto-vault ...
|
||||
} catch (raw) {
|
||||
if (CryptoVaultError.is(raw)) {
|
||||
switch (raw.code) {
|
||||
case CRYPTO_VAULT_CODES["SRP.AUTHENTICATION_FAILED"]:
|
||||
return { kind: "auth-failed" } as const;
|
||||
case CRYPTO_VAULT_CODES["SECURE.ZEROIZED"]:
|
||||
return { kind: "vault-locked" } as const;
|
||||
default:
|
||||
throw raw;
|
||||
}
|
||||
}
|
||||
throw raw;
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `class CryptoVaultError extends SuaveplanError<CryptoVaultCode>`
|
||||
|
||||
#### Constructor
|
||||
|
||||
`new CryptoVaultError(code, messageKey, options?)`
|
||||
|
||||
- `code: CryptoVaultCode` — fully-qualified registry code.
|
||||
- `messageKey: string` — i18n key resolved by `@suaveplan/error`'s
|
||||
`MessageResolver`.
|
||||
- `options?: SuaveplanErrorOptions` — forwarded to `SuaveplanError`.
|
||||
|
||||
#### `static is(value: unknown): value is CryptoVaultError`
|
||||
|
||||
Returns `true` when `value` was constructed by this package. Combines
|
||||
`instanceof` with a brand-symbol identity check, defending against cross-realm
|
||||
prototype divergence.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The brand symbol is a `unique symbol` keyed off
|
||||
`Symbol("@suaveplan/crypto-vault.error")`; the symbol identity is not
|
||||
stable across realms by design — `CryptoVaultError.is` uses it as a
|
||||
same-realm assertion only. Cross-realm instances must be re-thrown by
|
||||
their owning realm before reaching this guard.
|
||||
- The constructor sets the brand field after `super(...)` so the assignment
|
||||
happens after the prototype chain is initialised.
|
||||
- The class is intentionally non-abstract. Internal callers throw it
|
||||
directly with a `CRYPTO_VAULT_CODES.*` value rather than maintaining one
|
||||
subclass per error reason.
|
||||
Reference in New Issue
Block a user