@zeke-02/tinfoil 0.0.5 → 0.0.6

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/README.md CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  [![Build Status](https://github.com/tinfoilsh/tinfoil-node/actions/workflows/test.yml/badge.svg)](https://github.com/tinfoilsh/tinfoil-node/actions)
4
4
  [![NPM version](https://img.shields.io/npm/v/tinfoil.svg)](https://npmjs.org/package/tinfoil)
5
+ [![Documentation](https://img.shields.io/badge/docs-tinfoil.sh-blue)](https://docs.tinfoil.sh/sdk/node-sdk)
5
6
 
6
- This client library provides secure and convenient access to the Tinfoil Priavate Inference endpoints from TypeScript or JavaScript.
7
+ This client library provides secure and convenient access to the Tinfoil Private Inference endpoints from TypeScript or JavaScript.
7
8
 
8
9
  It is a wrapper around the OpenAI client that verifies enclave attestation and routes traffic to the Tinfoil Private Inference endpoints through an [EHBP](https://github.com/tinfoilsh/encrypted-http-body-protocol)-secured transport. EHBP encrypts all payloads directly to an attested enclave using [HPKE (RFC 9180)](https://www.rfc-editor.org/rfc/rfc9180.html).
9
10
 
@@ -69,7 +70,7 @@ const completion = await client.chat.completions.create({
69
70
 
70
71
  ## Verification helpers
71
72
 
72
- This package exposes verification helpers that load the Go-based WebAssembly verifier once per process and provide structured, stepwise attestation results you can use in applications (e.g., to show progress, log transitions, or gate features).
73
+ This package exposes verification helpers that load the Go-based WebAssembly verifier and provide end-to-end attestation with structured, stepwise results you can use in applications (e.g., to show progress, log transitions, or gate features).
73
74
 
74
75
  The verification functionality is contained in `verifier.ts`.
75
76
 
@@ -79,51 +80,62 @@ The verification functionality is contained in `verifier.ts`.
79
80
  ```typescript
80
81
  import { Verifier } from "tinfoil";
81
82
 
82
- const verifier = new Verifier();
83
-
84
- // Perform runtime attestation
85
- const runtime = await verifier.verifyEnclave("enclave.host.com");
86
- // Returns: { measurement: AttestationMeasurement, tlsPublicKeyFingerprint: string, hpkePublicKey: string }
87
-
88
- // Perform code attestation
89
- const code = await verifier.verifyCode("tinfoilsh/repo", "digest-hash");
90
- // Returns: { measurement: AttestationMeasurement }
91
-
92
- // Fetch latest digest from GitHub releases
93
- const digest = await verifier.fetchLatestDigest("tinfoilsh/repo");
83
+ const verifier = new Verifier({ serverURL: "https://enclave.host.com" });
84
+
85
+ // Perform full end-to-end verification
86
+ const attestation = await verifier.verify();
87
+ // Returns: AttestationResponse with measurement and cryptographic keys
88
+ // This performs all verification steps atomically:
89
+ // 1. Fetches the latest release digest from GitHub
90
+ // 2. Verifies code provenance using Sigstore
91
+ // 3. Performs runtime attestation against the enclave
92
+ // 4. Verifies hardware measurements (for TDX platforms)
93
+ // 5. Compares code and runtime measurements
94
+
95
+ // Access detailed verification results
96
+ const doc = verifier.getVerificationDocument();
97
+ // Returns: VerificationDocument with step-by-step status including
98
+ // measurements, fingerprints, and cryptographic keys
94
99
  ```
95
100
 
96
101
  ### Verification Document
97
102
 
98
- The `SecureClient` provides access to a comprehensive verification document that tracks all verification steps, including failures:
103
+ The `Verifier` provides access to a comprehensive verification document that tracks all verification steps, including failures:
99
104
 
100
105
  ```typescript
101
- import { SecureClient } from "tinfoil";
106
+ import { Verifier } from "tinfoil";
102
107
 
103
- const client = new SecureClient();
108
+ const verifier = new Verifier({ serverURL: "https://enclave.host.com" });
104
109
 
105
110
  try {
106
- await client.ready();
107
- const response = await client.fetch('https://api.example.com/data');
111
+ const attestation = await verifier.verify();
112
+ const doc = verifier.getVerificationDocument();
113
+ console.log('Security verified:', doc.securityVerified);
114
+ console.log('TLS fingerprint:', attestation.tlsPublicKeyFingerprint);
115
+ console.log('HPKE public key:', attestation.hpkePublicKey);
108
116
  } catch (error) {
109
117
  // Even on error, you can access the verification document
110
- const doc = await client.getVerificationDocument();
118
+ const doc = verifier.getVerificationDocument();
111
119
 
112
120
  // The document contains detailed step information:
113
121
  // - fetchDigest: GitHub release digest retrieval
114
122
  // - verifyCode: Code measurement verification
115
123
  // - verifyEnclave: Runtime attestation verification
116
124
  // - compareMeasurements: Code vs runtime measurement comparison
117
- // - createTransport: Transport initialization (optional)
118
- // - verifyHPKEKey: HPKE key verification (optional)
119
125
  // - otherError: Catch-all for unexpected errors (optional)
120
126
 
121
- console.log('Security verified:', doc.securityVerified);
122
-
123
127
  // Check individual steps
124
128
  if (doc.steps.verifyEnclave.status === 'failed') {
125
129
  console.log('Enclave verification failed:', doc.steps.verifyEnclave.error);
126
130
  }
131
+
132
+ // Error messages are prefixed with the failing step:
133
+ // - "fetchDigest:" - Failed to fetch GitHub release digest
134
+ // - "verifyCode:" - Failed to verify code provenance
135
+ // - "verifyEnclave:" - Failed runtime attestation
136
+ // - "verifyHardware:" - Failed TDX hardware verification
137
+ // - "validateTLS:" - TLS public key validation failed
138
+ // - "measurements:" - Measurement comparison failed
127
139
  }
128
140
  ```
129
141
 
@@ -156,6 +168,8 @@ See [examples/README.md](https://github.com/tinfoilsh/tinfoil-node/blob/main/exa
156
168
 
157
169
  ## API Documentation
158
170
 
171
+ For complete documentation on using the Tinfoil Node SDK, including advanced examples and API reference, visit the [official documentation](https://docs.tinfoil.sh/sdk/node-sdk).
172
+
159
173
  This library mirrors the official OpenAI Node.js client for common endpoints (e.g., chat, images, embeddings) and types, and is designed to feel familiar. Some less commonly used surfaces may not be fully covered. See the [OpenAI client](https://github.com/openai/openai-node) for complete API usage and documentation.
160
174
 
161
175
  ## Reporting Vulnerabilities
@@ -3,5 +3,5 @@ interface CreateTinfoilAIOptions {
3
3
  enclaveURL?: string;
4
4
  configRepo?: string;
5
5
  }
6
- export declare function createTinfoilAI(apiKey: string, options?: CreateTinfoilAIOptions): Promise<import("@ai-sdk/openai-compatible").OpenAICompatibleProvider<string, string, string, string>>;
6
+ export declare function createTinfoilAI(apiKey: string, options?: CreateTinfoilAIOptions, headers?: Record<string, string>): Promise<import("@ai-sdk/openai-compatible").OpenAICompatibleProvider<string, string, string, string>>;
7
7
  export {};
@@ -4,7 +4,7 @@ exports.createTinfoilAI = createTinfoilAI;
4
4
  const openai_compatible_1 = require("@ai-sdk/openai-compatible");
5
5
  const config_1 = require("./config");
6
6
  const secure_client_1 = require("./secure-client");
7
- async function createTinfoilAI(apiKey, options = {}) {
7
+ async function createTinfoilAI(apiKey, options = {}, headers = {}) {
8
8
  const baseURL = options.baseURL;
9
9
  const enclaveURL = options.enclaveURL;
10
10
  const configRepo = options.configRepo || config_1.TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
@@ -24,5 +24,6 @@ async function createTinfoilAI(apiKey, options = {}) {
24
24
  baseURL: finalBaseURL,
25
25
  apiKey: apiKey,
26
26
  fetch: secureClient.fetch,
27
+ headers,
27
28
  });
28
29
  }
@@ -3,5 +3,5 @@ interface CreateTinfoilAIOptions {
3
3
  enclaveURL?: string;
4
4
  configRepo?: string;
5
5
  }
6
- export declare function createTinfoilAI(apiKey: string, options?: CreateTinfoilAIOptions): Promise<import("@ai-sdk/openai-compatible").OpenAICompatibleProvider<string, string, string, string>>;
6
+ export declare function createTinfoilAI(apiKey: string, options?: CreateTinfoilAIOptions, headers?: Record<string, string>): Promise<import("@ai-sdk/openai-compatible").OpenAICompatibleProvider<string, string, string, string>>;
7
7
  export {};
@@ -1,7 +1,7 @@
1
1
  import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
2
2
  import { TINFOIL_CONFIG } from "./config.mjs";
3
3
  import { SecureClient } from "./secure-client.mjs";
4
- export async function createTinfoilAI(apiKey, options = {}) {
4
+ export async function createTinfoilAI(apiKey, options = {}, headers = {}) {
5
5
  const baseURL = options.baseURL;
6
6
  const enclaveURL = options.enclaveURL;
7
7
  const configRepo = options.configRepo || TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
@@ -21,5 +21,6 @@ export async function createTinfoilAI(apiKey, options = {}) {
21
21
  baseURL: finalBaseURL,
22
22
  apiKey: apiKey,
23
23
  fetch: secureClient.fetch,
24
+ headers,
24
25
  });
25
26
  }
@@ -82,12 +82,20 @@ export class SecureClient {
82
82
  releaseDigest: "",
83
83
  codeMeasurement: { type: "", registers: [] },
84
84
  enclaveMeasurement: { measurement: { type: "", registers: [] } },
85
+ tlsPublicKey: "",
86
+ hpkePublicKey: "",
87
+ hardwareMeasurement: undefined,
88
+ codeFingerprint: "",
89
+ enclaveFingerprint: "",
90
+ selectedRouterEndpoint: new URL(this.enclaveURL).hostname,
85
91
  securityVerified: false,
86
92
  steps: {
87
93
  fetchDigest: { status: "pending" },
88
94
  verifyCode: { status: "pending" },
89
95
  verifyEnclave: { status: "pending" },
90
96
  compareMeasurements: { status: "pending" },
97
+ createTransport: undefined,
98
+ verifyHPKEKey: undefined,
91
99
  otherError: { status: "failed", error: error.message },
92
100
  },
93
101
  };
@@ -5,6 +5,14 @@ export interface AttestationMeasurement {
5
5
  type: string;
6
6
  registers: string[];
7
7
  }
8
+ /**
9
+ * Hardware measurement from TDX platform verification
10
+ */
11
+ export interface HardwareMeasurement {
12
+ ID: string;
13
+ MRTD: string;
14
+ RTMR0: string;
15
+ }
8
16
  /**
9
17
  * Attestation response containing cryptographic keys and measurements
10
18
  * At least one of tlsPublicKeyFingerprint or hpkePublicKey must be present
@@ -31,6 +39,12 @@ export interface VerificationDocument {
31
39
  releaseDigest: string;
32
40
  codeMeasurement: AttestationMeasurement;
33
41
  enclaveMeasurement: AttestationResponse;
42
+ tlsPublicKey: string;
43
+ hpkePublicKey: string;
44
+ hardwareMeasurement?: HardwareMeasurement;
45
+ codeFingerprint: string;
46
+ enclaveFingerprint: string;
47
+ selectedRouterEndpoint: string;
34
48
  securityVerified: boolean;
35
49
  steps: {
36
50
  fetchDigest: VerificationStepState;
@@ -42,29 +56,19 @@ export interface VerificationDocument {
42
56
  otherError?: VerificationStepState;
43
57
  };
44
58
  }
45
- export interface MeasurementComparisonResult {
46
- match: boolean;
47
- error?: Error;
48
- }
49
- export declare function compareMeasurementsDetailed(codeMeasurement: AttestationMeasurement, runtimeMeasurement: AttestationMeasurement): MeasurementComparisonResult;
50
- /**
51
- * Compare two measurements according to platform-specific rules
52
- * This is predicate function for comparing attestation measurements
53
- * taken from https://github.com/tinfoilsh/verifier/blob/main/attestation/attestation.go
54
- *
55
- * @param codeMeasurement - Expected measurement from code attestation
56
- * @param runtimeMeasurement - Actual measurement from runtime attestation
57
- * @returns true if measurements match according to platform rules
58
- */
59
- export declare function compareMeasurements(codeMeasurement: AttestationMeasurement, runtimeMeasurement: AttestationMeasurement): boolean;
60
59
  /**
61
60
  * Verifier performs attestation verification for Tinfoil enclaves
62
61
  *
63
- * The verifier loads a WebAssembly module that:
62
+ * The verifier loads a WebAssembly module (compiled from Go) that performs
63
+ * end-to-end attestation verification:
64
64
  * 1. Fetches the latest code release digest from GitHub
65
- * 2. Performs runtime attestation against the enclave
66
- * 3. Performs code attestation using the digest
67
- * 4. Compares measurements using platform-specific logic
65
+ * 2. Verifies code provenance using Sigstore/Rekor
66
+ * 3. Performs runtime attestation against the enclave
67
+ * 4. Verifies hardware measurements (for TDX platforms)
68
+ * 5. Compares code and runtime measurements using platform-specific logic
69
+ *
70
+ * Primary method: verify() - Returns AttestationResponse with cryptographic keys
71
+ * Verification details: getVerificationDocument() - Returns step-by-step results
68
72
  */
69
73
  export declare class Verifier {
70
74
  private static goInstance;
@@ -86,56 +90,52 @@ export declare class Verifier {
86
90
  */
87
91
  private static executeWithWasm;
88
92
  /**
89
- * Fetch the latest release digest from GitHub
90
- * @param configRepo - Repository name (e.g., "tinfoilsh/confidential-model-router")
91
- * @returns The digest hash
92
- */
93
- fetchLatestDigest(configRepo?: string): Promise<string>;
94
- /**
95
- * Perform runtime attestation on the enclave
96
- * @param enclaveHost - The enclave hostname
97
- * @returns Attestation response with measurement and keys
98
- */
99
- verifyEnclave(enclaveHost?: string): Promise<AttestationResponse>;
100
- /**
101
- * Perform code attestation
102
- * @param configRepo - Repository name
103
- * @param digest - Code digest hash
104
- * @returns Code measurement
105
- */
106
- verifyCode(configRepo: string, digest: string): Promise<{
107
- measurement: AttestationMeasurement;
108
- }>;
109
- /**
110
- * Perform attestation verification
93
+ * Perform end-to-end attestation verification
111
94
  *
112
- * This method:
95
+ * This method performs all verification steps atomically via the Go WASM verify() function:
113
96
  * 1. Fetches the latest code digest from GitHub releases
114
- * 2. Calls verifyCode to get the expected measurement for the code
115
- * 3. Calls verifyEnclave to get the actual runtime measurement
116
- * 4. Compares measurements using platform-specific logic (see `compareMeasurements()`)
117
- * 5. Returns the attestation response if verification succeeds
97
+ * 2. Verifies code provenance using Sigstore/Rekor
98
+ * 3. Performs runtime attestation against the enclave
99
+ * 4. Verifies hardware measurements (for TDX platforms)
100
+ * 5. Compares code and runtime measurements using platform-specific logic
118
101
  *
119
102
  * The WASM runtime is automatically initialized and cleaned up within this method.
103
+ * A detailed verification document is saved and can be accessed via getVerificationDocument().
120
104
  *
121
- * @throws Error if measurements don't match or verification fails
105
+ * @returns AttestationResponse containing cryptographic keys (TLS/HPKE) and enclave measurement
106
+ * @throws Error if measurements don't match or verification fails at any step
122
107
  */
123
108
  verify(): Promise<AttestationResponse>;
109
+ /**
110
+ * Save a failed verification document
111
+ */
112
+ private saveFailedVerificationDocument;
124
113
  /**
125
114
  * Internal verification logic that runs within WASM context
126
115
  */
127
116
  private verifyInternal;
128
117
  /**
129
- * Returns the full verification document from the last successful verify() call
118
+ * Returns the verification document from the last verify() call
119
+ *
120
+ * The document contains detailed step-by-step verification results including:
121
+ * - Step status (pending/success/failed) for each verification phase
122
+ * - Measurements, fingerprints, and cryptographic keys
123
+ * - Error messages for any failed steps
124
+ *
125
+ * Available even if verification failed, allowing inspection of which step failed.
126
+ *
127
+ * @returns VerificationDocument with complete verification details, or undefined if verify() hasn't been called
130
128
  */
131
129
  getVerificationDocument(): VerificationDocument | undefined;
132
130
  }
133
131
  /**
134
132
  * Control WASM log output
135
133
  *
136
- * The Go WASM runtime outputs logs through a polyfilled fs.writeSync.
134
+ * The Go WASM runtime outputs logs (stdout/stderr) through a polyfilled fs.writeSync.
137
135
  * This function allows suppressing those logs without affecting other console output.
136
+ * By default, WASM logs are suppressed to reduce noise.
138
137
  *
139
138
  * @param suppress - Whether to suppress WASM logs (default: true)
139
+ * @returns void
140
140
  */
141
141
  export declare function suppressWasmLogs(suppress?: boolean): void;