feat: align timeout, error types and docs with the Python SDK
All checks were successful
NYX Security Scan / nyx-scan (pull_request) Successful in 5m43s
All checks were successful
NYX Security Scan / nyx-scan (pull_request) Successful in 5m43s
Completes the parity work (step 4). Request timeout now defaults to 900 s, matching Python, instead of 60 s. Encrypted inference cannot stream, so an entire completion arrives in one response; a long generation on a busy backend legitimately takes minutes and was timing out here while succeeding in the Python client. Error types now distinguish malformed data from integrity failures. Python raises ValueError for a bad package, a non-200 or unparseable /pki/public_key, and plaintext that will not parse, reserving SecurityError for crypto failures. This port wrapped nearly all of it in SecurityError — so a server sending malformed JSON was reported as an authentication failure, pointing debugging in exactly the wrong direction. Malformed data is now a plain Error (the JS equivalent of ValueError), carried past the deliberately opaque catch-all by a symbol marker rather than a new exported class. Genuine crypto failures still report a single vague message so they cannot serve as a decryption oracle. Also adds the missing guard Python has: decrypting without a private key now says so, instead of failing later and being reported as an integrity failure. doc/attestation.md ports the Python attestation guide to the JS API, and documents the two deliberate divergences: no verify_ssl escape hatch, and jose injection instead of a runtime dynamic import. Version 0.1.0 -> 0.3.0 to match the Python client's feature level, now that the two are at parity. Not ported: Python's warning when secure_memory=True but the SecureMemory module is unavailable. There is no JS equivalent — zeroing is always available, and the weaker case (mlock unavailable) is already reported honestly by getProtectionInfo(). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
00388ccb01
commit
eafab3d9ac
10 changed files with 535 additions and 17 deletions
|
|
@ -19,13 +19,15 @@ new SecureChatCompletion(config?: ChatCompletionConfig)
|
|||
| `allowHttp` | `boolean` | `false` | Allow HTTP connections.**Local development only.** |
|
||||
| `apiKey` | `string` | `undefined` | Bearer token sent in`Authorization` header. |
|
||||
| `secureMemory` | `boolean` | `true` | Enable immediate zeroing of sensitive buffers after use. |
|
||||
| `timeout` | `number` | `60000` | Request timeout in milliseconds. |
|
||||
| `timeout` | `number` | `900000` (15 min) | Request timeout in milliseconds. Encrypted inference cannot stream, so the whole completion arrives in one response; long generations legitimately take minutes. |
|
||||
| `debug` | `boolean` | `false` | Print verbose logging to the console. |
|
||||
| `keyDir` | `string \| null` | `null` | Directory to load/save RSA keys on startup. If the directory contains an existing key pair it is loaded; otherwise a new pair is generated and saved there. Omit (or pass `null`) for ephemeral keys generated in memory for this session only and never written to disk — this is the default, matching the Python SDK. Node.js only; browsers are always ephemeral. |
|
||||
| `keyRotationInterval` | `number` | `86400000` (24 h) | Auto-rotate RSA keys every N milliseconds. Set to`0` to disable. |
|
||||
| `keyRotationDir` | `string` | value of `keyDir` | Directory where rotated key files are saved. When neither this nor `keyDir` is set, rotated keys stay in memory. Node.js only. |
|
||||
| `keyRotationPassword` | `string` | `undefined` | Password used to encrypt rotated key files. |
|
||||
| `maxRetries` | `number` | `2` | Maximum extra attempts on retryable errors (429, 500, 502, 503, 504, network errors). Uses exponential backoff (1 s, 2 s, …). Set to`0` to disable retries. |
|
||||
| `attestationPolicy` | `AttestationPolicy` | `undefined` | Enables SGX attestation verification before any plaintext is sent. Omit to disable. See [Attestation](attestation.md). |
|
||||
| `quoteVerifier` | `QuoteVerifier` | `undefined` | Performs the DCAP quote verification (e.g.`JwtQuoteVerifier`). Required for a policy to actually verify; without one, a set policy treats attestation as unverifiable. |
|
||||
|
||||
### Methods
|
||||
|
||||
|
|
@ -251,6 +253,7 @@ import {
|
|||
ServiceUnavailableError,
|
||||
APIConnectionError,
|
||||
SecurityError,
|
||||
AttestationError,
|
||||
DisposedError,
|
||||
} from 'nomyo-js';
|
||||
```
|
||||
|
|
@ -267,6 +270,36 @@ import {
|
|||
| `APIError` | varies | Other HTTP errors (404, 502, 504, etc.) |
|
||||
| `APIConnectionError` | — | Network failure or timeout (after all retries exhausted) |
|
||||
| `SecurityError` | — | HTTPS not used, header injection detected, or crypto failure |
|
||||
| `AttestationError` | — | SGX attestation failed under`enforce` (extends `SecurityError`) |
|
||||
| `DisposedError` | — | Method called after`dispose()` |
|
||||
|
||||
All errors that extend `APIError` expose `statusCode?: number` and `errorDetails?: object`.
|
||||
|
||||
### Malformed data vs security failures
|
||||
|
||||
A plain `Error` — not a `SecurityError` — is thrown when a response is
|
||||
structurally wrong rather than cryptographically suspect: a missing package
|
||||
field, an unsupported protocol version, a non-200 or unparseable
|
||||
`/pki/public_key` response, or plaintext that decrypted and authenticated
|
||||
successfully but is not valid JSON.
|
||||
|
||||
`SecurityError` is reserved for actual security conditions, and stays
|
||||
deliberately vague about which stage failed so it cannot be used as a decryption
|
||||
oracle:
|
||||
|
||||
```typescript
|
||||
try {
|
||||
await client.create({ model, messages });
|
||||
} catch (error) {
|
||||
if (error instanceof SecurityError) {
|
||||
// integrity/authentication failure, HTTPS violation, or failed attestation
|
||||
} else if (error instanceof APIError) {
|
||||
// server responded with an HTTP error
|
||||
} else {
|
||||
// malformed response data
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This mirrors the Python SDK, which raises `ValueError` where this client throws
|
||||
a plain `Error`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue