@terminal3/t3n-sdk 0.7.0 → 0.10.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.
Files changed (49) hide show
  1. package/dist/index.d.ts +266 -294
  2. package/dist/index.esm.js +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/src/client/config.d.ts +30 -10
  5. package/dist/src/client/index.d.ts +0 -4
  6. package/dist/src/client/t3n-client.d.ts +27 -64
  7. package/dist/src/config/index.d.ts +36 -2
  8. package/dist/src/index.d.ts +9 -8
  9. package/dist/src/types/auth.d.ts +6 -5
  10. package/dist/src/types/index.d.ts +13 -37
  11. package/dist/src/utils/hkdf.d.ts +36 -0
  12. package/dist/src/utils/index.d.ts +1 -0
  13. package/dist/src/wasm/interface.d.ts +54 -89
  14. package/dist/src/wasm/loader.d.ts +55 -25
  15. package/dist/src/wasm/quote-verifier/quote_verifier_bytes.d.ts +1 -0
  16. package/dist/src/wasm/quote-verifier-loader.d.ts +58 -0
  17. package/dist/wasm/generated/interfaces/host-session-interfaces-contract-dispatch.d.ts +2 -0
  18. package/dist/wasm/generated/interfaces/host-session-interfaces-entropy.d.ts +2 -0
  19. package/dist/wasm/generated/interfaces/host-session-interfaces-eth-signer.d.ts +2 -0
  20. package/dist/wasm/generated/interfaces/host-session-interfaces-kem.d.ts +3 -0
  21. package/dist/wasm/generated/interfaces/host-session-interfaces-oidc-client.d.ts +2 -0
  22. package/dist/wasm/generated/interfaces/host-session-interfaces-oidc.d.ts +3 -0
  23. package/dist/wasm/generated/interfaces/host-session-interfaces-session-ops.d.ts +9 -0
  24. package/dist/wasm/generated/interfaces/host-session-interfaces-transport.d.ts +2 -0
  25. package/dist/wasm/generated/interfaces/tee-session-client-auth.d.ts +7 -0
  26. package/dist/wasm/generated/interfaces/tee-session-client-handshake.d.ts +12 -0
  27. package/dist/wasm/generated/interfaces/tee-session-cookie.d.ts +7 -0
  28. package/dist/wasm/generated/interfaces/tee-session-server-admin.d.ts +2 -0
  29. package/dist/wasm/generated/interfaces/tee-session-server-auth.d.ts +10 -0
  30. package/dist/wasm/generated/interfaces/tee-session-server-handshake.d.ts +15 -0
  31. package/dist/wasm/generated/interfaces/tee-session-server-webhook.d.ts +6 -0
  32. package/dist/wasm/generated/interfaces/tee-session-session-crypto.d.ts +3 -0
  33. package/dist/wasm/generated/session.core.wasm +0 -0
  34. package/dist/wasm/generated/session.core2.wasm +0 -0
  35. package/dist/wasm/generated/session.core3.wasm +0 -0
  36. package/dist/wasm/generated/session.d.ts +87 -12
  37. package/dist/wasm/generated/session.js +6640 -3702
  38. package/package.json +1 -1
  39. package/dist/demo.d.ts +0 -25
  40. package/dist/src/client/actions.d.ts +0 -22
  41. package/dist/src/client/encryption.d.ts +0 -30
  42. package/dist/src/client/handlers.d.ts +0 -73
  43. package/dist/src/client/request-parser.d.ts +0 -48
  44. package/dist/wasm/generated/interfaces/component-session-client-auth.d.ts +0 -12
  45. package/dist/wasm/generated/interfaces/component-session-client-handshake.d.ts +0 -12
  46. package/dist/wasm/generated/interfaces/component-session-cookie.d.ts +0 -8
  47. package/dist/wasm/generated/interfaces/component-session-server-auth.d.ts +0 -13
  48. package/dist/wasm/generated/interfaces/component-session-server-handshake.d.ts +0 -12
  49. package/dist/wasm/generated/interfaces/component-session-session.d.ts +0 -7
package/dist/index.d.ts CHANGED
@@ -1,106 +1,71 @@
1
1
  /**
2
- * WASM Component Interface - Mirrors the WIT specification exactly
2
+ * WASM Component Interface async direct-call.
3
3
  *
4
- * This interface works with completely opaque byte arrays, just like the WIT interface.
5
- * The TypeScript SDK doesn't know about internal state machine phases or details.
4
+ * Mirrors `tee:session@1.0.0` WIT world. The SDK talks to the WASM
5
+ * only through these exports (plus host imports supplied at
6
+ * instantiation); all protocol glue lives inside the contract.
6
7
  */
7
- /**
8
- * Result type for WASM next() operations
9
- */
10
- interface WasmNextResult {
11
- state: Uint8Array;
12
- request: Uint8Array;
8
+ interface ClientSessionKeys {
9
+ /** `encrypt_key || decrypt_key`, 64 bytes. */
10
+ blob: Uint8Array;
11
+ sid: Uint8Array;
12
+ }
13
+ interface HandshakeOutcome {
14
+ keys: ClientSessionKeys;
15
+ authenticated: boolean;
16
+ did?: string;
17
+ expirySec: bigint;
13
18
  }
14
- /**
15
- * Client handshake operations - completely opaque byte arrays only
16
- */
17
19
  interface ClientHandshake {
18
- /**
19
- * Process next step in handshake
20
- * @param state - Current handshake state (null for initial call)
21
- * @param action - Action to process (opaque bytes)
22
- * @returns Promise with new state and request to send
23
- */
24
- next(state: Uint8Array | null, action: Uint8Array): Promise<WasmNextResult>;
25
- /**
26
- * Attempt to finalize handshake
27
- * @param state - Current handshake state
28
- * @returns Promise with session bytes if successful
29
- * @throws Error if handshake not ready to finalize
30
- */
31
- finish(state: Uint8Array): Promise<Uint8Array>;
20
+ run(sid: Uint8Array, cookie: string | undefined): HandshakeOutcome;
21
+ }
22
+ interface AuthOutcome {
23
+ did: string;
24
+ cookie?: string;
32
25
  }
33
- /**
34
- * Client authentication operations - completely opaque byte arrays only
35
- */
36
26
  interface ClientAuth {
27
+ runEth(sessionKeys: Uint8Array, ethAddress: string, siweDomain: string | undefined, siweUrl: string | undefined, siweChainId: bigint | undefined): AuthOutcome;
37
28
  /**
38
- * Process next step in authentication
39
- * @param state - Current auth state (null for initial call)
40
- * @param action - Action to process (opaque bytes)
41
- * @returns Promise with new state and request to send
42
- */
43
- next(state: Uint8Array | null, action: Uint8Array): Promise<WasmNextResult>;
44
- /**
45
- * Attempt to finalize authentication
46
- * @param state - Current auth state
47
- * @returns Promise with DID bytes if successful
48
- * @throws Error if authentication not ready to finalize
29
+ * Run the full OIDC flow in one call. The contract drives both
30
+ * server round-trips and invokes the SDK's `getIdToken(provider,
31
+ * nonce)` host import in between to obtain the IdP-signed token.
49
32
  */
50
- finish(state: Uint8Array): Promise<Uint8Array>;
33
+ runOidc(sessionKeys: Uint8Array, provider: string): AuthOutcome;
51
34
  }
52
- /**
53
- * Client authentication operations - completely opaque byte arrays only
54
- */
55
- interface ClientExecute {
56
- /**
57
- * Process next step in authentication
58
- * @param state - Current auth state (null for initial call)
59
- * @param action - Action to process (opaque bytes)
60
- * @returns Promise with new state and request to send
61
- */
62
- next(state: Uint8Array | null, action: Uint8Array): Promise<WasmNextResult>;
63
- /**
64
- * Attempt to finalize authentication
65
- * @param state - Current auth state
66
- * @returns Promise with DID bytes if successful
67
- * @throws Error if authentication not ready to finalize
68
- */
69
- finish(state: Uint8Array): Promise<Uint8Array>;
35
+ interface ServerSessionKeys {
36
+ c2s: Uint8Array;
37
+ s2c: Uint8Array;
38
+ sid: Uint8Array;
39
+ }
40
+ interface ServerOutcome {
41
+ keys: ServerSessionKeys;
42
+ authenticated: boolean;
43
+ did?: string;
44
+ expirySec: bigint;
45
+ refreshedCookie?: string;
46
+ }
47
+ interface ServerHandshake {
48
+ run(sid: Uint8Array, ciphertext: Uint8Array, cookieValue: string | undefined): ServerOutcome;
70
49
  }
71
- /**
72
- * Session encryption/decryption operations - completely opaque byte arrays only
73
- */
74
50
  interface SessionCrypto {
75
- /**
76
- * Encrypt plaintext using session
77
- * @param session - Session state (opaque bytes)
78
- * @param plaintext - Data to encrypt
79
- * @returns Promise with encrypted bytes
80
- */
81
- encrypt(session: Uint8Array, plaintext: Uint8Array): Promise<Uint8Array>;
82
- /**
83
- * Decrypt ciphertext using session
84
- * @param session - Session state (opaque bytes)
85
- * @param ciphertext - Data to decrypt
86
- * @returns Promise with decrypted bytes
87
- */
88
- decrypt(session: Uint8Array, ciphertext: Uint8Array): Promise<Uint8Array>;
51
+ encrypt(keys: Uint8Array, plaintext: Uint8Array): Uint8Array;
52
+ decrypt(keys: Uint8Array, ciphertext: Uint8Array): Uint8Array;
89
53
  }
90
- /**
91
- * Main WASM Component interface - mirrors the WIT interface exactly
92
- *
93
- * This is completely opaque to the TypeScript layer. All state machine logic,
94
- * authentication flows, and cryptographic operations are handled in WASM.
95
- */
54
+ interface Validation {
55
+ authenticated: boolean;
56
+ did?: string;
57
+ exp: bigint;
58
+ }
59
+ interface CookieIface {
60
+ validate(cookieValue: string, teeAddress: Uint8Array, nowSec: bigint): Validation;
61
+ }
62
+ /** Fully instantiated session component. */
96
63
  interface WasmComponent {
97
- /** Client handshake operations */
98
- flow: {
99
- handshake: ClientHandshake;
100
- auth: ClientAuth;
101
- execute: ClientExecute;
102
- };
103
- session: SessionCrypto;
64
+ clientHandshake: ClientHandshake;
65
+ clientAuth: ClientAuth;
66
+ serverHandshake: ServerHandshake;
67
+ sessionCrypto: SessionCrypto;
68
+ cookie: CookieIface;
104
69
  }
105
70
 
106
71
  /**
@@ -207,38 +172,75 @@ declare function createLogger(level?: LogLevel): Logger;
207
172
  declare function getLogger(): Logger;
208
173
 
209
174
  /**
210
- * WASM Component Loader
175
+ * WASM Component Loader — async direct-call shape.
176
+ *
177
+ * Loads the `tee:session@1.0.0` jco-transpiled component. Host
178
+ * imports (`host:session-interfaces/*`) are supplied at
179
+ * instantiation; the caller can override any of them via
180
+ * `WasmLoadConfig.hostImports` to plug a custom KEM public-key
181
+ * source, ETH signer, etc. Defaults cover the common case for the
182
+ * browser SDK:
211
183
  *
212
- * This module provides utilities for loading and initializing the WASM component.
213
- * The actual WASM loading implementation will depend on the build system and
214
- * deployment environment.
184
+ * - `entropy.random`: WebCrypto `getRandomValues`
185
+ * - `kem.mlKemPublicKey`: HTTP fetch of /pubkey (caller sets URL)
186
+ * - `kem.decapsulate`: server-only; client-side stub returns error
187
+ * - `eth-signer.eth-sign`: injected wallet (window.ethereum) if present
188
+ * - `session-ops.now-ms`: Date.now()
189
+ * - `session-ops.tee-address`, `set-cookie`: caller-supplied or stubs
215
190
  */
216
191
 
192
+ /**
193
+ * Host imports supplied at WASM instantiation. Any subset may be
194
+ * overridden by the caller; unset ones fall back to a safe default
195
+ * (or an error stub for server-only methods like `decapsulate`).
196
+ */
197
+ interface SessionHostImports {
198
+ /** Fetch the server's ML-KEM public key (client-side). */
199
+ mlKemPublicKey?: () => Uint8Array | Promise<Uint8Array>;
200
+ /** CSPRNG. Defaults to WebCrypto `getRandomValues`. */
201
+ random?: (len: number) => Uint8Array;
202
+ /** EIP-191 / SIWE signer. Defaults to error (caller must supply). */
203
+ ethSign?: (message: Uint8Array) => Uint8Array | Promise<Uint8Array>;
204
+ /**
205
+ * OIDC user-interaction callback. The contract supplies the
206
+ * server-bound `nonce`; the SDK consumer runs whatever popup /
207
+ * redirect flow is appropriate for `provider` and returns the
208
+ * IdP-signed `id_token`. Defaults to error (caller must supply
209
+ * when using OIDC auth).
210
+ */
211
+ getIdToken?: (provider: string, nonce: string) => string | Promise<string>;
212
+ /** Current time in ms. Defaults to Date.now() (as bigint). */
213
+ nowMs?: () => bigint;
214
+ /** TEE address — server-only; client stub returns 20 zero bytes. */
215
+ teeAddress?: () => Uint8Array;
216
+ /** Called when the guest emits a refreshed cookie. */
217
+ setCookie?: (value: string) => void;
218
+ /**
219
+ * HTTP transport the contract uses to POST JSON-RPC requests. The
220
+ * SDK wires this to its `Transport` under the hood — the contract
221
+ * supplies the method name and params bytes; the SDK layers on the
222
+ * Session-Id header, JSON-RPC envelope, and returns the raw result
223
+ * bytes.
224
+ */
225
+ postRpc?: (method: string, sessionId: string, params: string) => string | Promise<string>;
226
+ }
217
227
  /**
218
228
  * Configuration for WASM component loading
219
229
  */
220
230
  interface WasmLoadConfig {
221
231
  /** Path or URL to the WASM module */
222
232
  wasmPath?: string;
223
- /** Custom fetch function for loading WASM */
224
- fetchFn?: typeof fetch;
225
- /** Additional initialization options */
226
- initOptions?: Record<string, unknown>;
227
233
  /** Optional logger instance - if not provided, uses global default */
228
234
  logger?: Logger;
235
+ /** Overrides for the host-import functions. */
236
+ hostImports?: SessionHostImports;
229
237
  }
230
238
  /**
231
- * Load and initialize the T3n WASM component
232
- *
233
- * @param config - Optional configuration for loading the WASM component
234
- * @returns Promise that resolves to the initialized WASM component
239
+ * Load and initialize the T3n WASM component (async direct-call).
235
240
  *
236
- * @example
237
- * ```typescript
238
- * const wasmComponent = await loadWasmComponent({
239
- * wasmPath: '/path/to/t3n.wasm'
240
- * });
241
- * ```
241
+ * The caller normally only needs to override `mlKemPublicKey` (to
242
+ * point at the node URL) and `ethSign` (to bridge to the browser
243
+ * wallet). All other imports have sensible defaults.
242
244
  */
243
245
  declare function loadWasmComponent(config?: WasmLoadConfig): Promise<WasmComponent>;
244
246
 
@@ -280,14 +282,15 @@ declare enum AuthMethod {
280
282
  /**
281
283
  * OIDC credentials interface.
282
284
  *
283
- * The TEE generates a session-binding nonce that must be included in
284
- * the Google authorization URL (`&nonce=…`). The `getIdToken` callback
285
- * receives this nonce and must return the `id_token` JWT obtained
286
- * from the OIDC provider with the nonce baked into its claims.
285
+ * The TEE generates a session-binding nonce; the user-interaction
286
+ * step is wired at WASM load time via `hostImports.getIdToken`
287
+ * (see `loadWasmComponent`), mirroring how `hostImports.ethSign`
288
+ * supplies wallet access. The contract calls `getIdToken(provider,
289
+ * nonce)` from inside `runOidc` and feeds the returned `id_token`
290
+ * to the server.
287
291
  */
288
292
  interface OidcCredentials {
289
293
  provider: string;
290
- getIdToken: (nonce: string) => Promise<string>;
291
294
  }
292
295
  /**
293
296
  * Base authentication input with method discriminator
@@ -319,47 +322,6 @@ type AuthInput = EthAuthInput | OidcAuthInput;
319
322
  declare function createEthAuthInput(address: string): EthAuthInput;
320
323
  declare function createOidcAuthInput(credentials: OidcCredentials): OidcAuthInput;
321
324
 
322
- /**
323
- * Public types export for T3n SDK
324
- */
325
- /**
326
- * Guest-to-Host request handler function type
327
- *
328
- * Handles requests from WASM guest that need host (SDK) to perform side
329
- * effects. The exact shape of `requestData` depends on the specific
330
- * handler — see `GuestToHostHandlers` below for the per-handler shapes.
331
- * The wrapper layer in `T3nClient.handleGuestToHost` parses the JSON
332
- * envelope and calls the matching handler with the parsed data, so
333
- * each handler's implementation should narrow `requestData` to its
334
- * own expected shape.
335
- */
336
- type GuestToHostHandler = (requestData: Record<string, unknown>) => Promise<Uint8Array>;
337
- /**
338
- * Map of guest-to-host request handlers
339
- * Keys match the guest_to_host tag values from the WASM
340
- */
341
- interface GuestToHostHandlers {
342
- /**
343
- * Handle Ethereum signature requests
344
- * requestData: { guest_to_host: "EthSign", challenge: string (base64) }
345
- * Returns: JSON bytes of { host_to_guest: "EthSign", challenge: string, signature: string }
346
- */
347
- EthSign?: GuestToHostHandler;
348
- /**
349
- * Handle MlKem public key requests
350
- * requestData: { guest_to_host: "MlKemPublicKey" }
351
- * Returns: JSON bytes of { host_to_guest: "MlKemPublicKey", key: string }
352
- */
353
- MlKemPublicKey?: GuestToHostHandler;
354
- /**
355
- * Handle random bytes requests
356
- * requestData: { guest_to_host: "Random", len?: number }
357
- * Returns: JSON bytes of { host_to_guest: "Random", bytes: string (base64) }
358
- */
359
- Random?: GuestToHostHandler;
360
- [key: string]: GuestToHostHandler | undefined;
361
- }
362
-
363
325
  /**
364
326
  * Transport layer for T3n SDK
365
327
  *
@@ -478,7 +440,7 @@ declare class MockTransport implements Transport {
478
440
  interface T3nClientConfig {
479
441
  /** Base URL of the T3n node (used if transport not provided) */
480
442
  baseUrl?: string;
481
- /** WASM component instance for cryptographic operations */
443
+ /** WASM component instance (async direct-call `tee:session@1.0.0`). */
482
444
  wasmComponent: WasmComponent;
483
445
  /** Optional transport layer - if not provided, uses HttpTransport with baseUrl */
484
446
  transport?: Transport;
@@ -488,171 +450,90 @@ interface T3nClientConfig {
488
450
  timeout?: number;
489
451
  /** Optional custom headers to include in requests */
490
452
  headers?: Record<string, string>;
491
- /**
492
- * Log level for this client instance.
493
- * Defaults to global log level (LogLevel.ERROR) if not specified.
494
- * Use LogLevel.DEBUG for verbose logging, LogLevel.INFO for informational messages,
495
- * LogLevel.WARN for warnings, or LogLevel.ERROR for errors only.
496
- */
453
+ /** Log level for this client instance. */
497
454
  logLevel?: LogLevel;
498
455
  /** Optional custom logger - if provided, overrides logLevel */
499
456
  logger?: Logger;
500
- /** Optional guest-to-host request handlers - provides custom behavior for WASM requests */
501
- handlers?: GuestToHostHandlers;
457
+ /**
458
+ * Optional signer bridge used by `authenticate()` for the ETH
459
+ * (SIWE) flow. Given the SIWE message bytes, the callback must
460
+ * produce a 65-byte `(r || s || v)` signature over the EIP-191
461
+ * personal-sign digest — matching `cryptography::ecdsa::eth`
462
+ * recovery on the node. A convenience wrapper for raw-private-key
463
+ * signing is planned for the follow-up commit that lands full
464
+ * ETH auth support.
465
+ */
466
+ ethSign?: (message: Uint8Array) => Promise<Uint8Array>;
467
+ /**
468
+ * Ethereum address (0x-prefixed, 20 bytes hex) of the user
469
+ * authenticating. Required by `authenticate()` for the ETH flow —
470
+ * the server recovers the signer from the SIWE message and
471
+ * compares to this address.
472
+ */
473
+ ethAddress?: string;
474
+ /**
475
+ * SIWE domain / URI / chain-id used in the message the SDK builds.
476
+ * Matches `SiwePolicy` on the server — the server's allowlist
477
+ * policy (if configured in NodeConfig) only accepts matching
478
+ * values. Defaults: domain `"localhost"`, URL `"https://trinity.io"`,
479
+ * chain ID `1` (Ethereum mainnet).
480
+ */
481
+ siweDomain?: string;
482
+ siweUrl?: string;
483
+ siweChainId?: number;
502
484
  }
503
485
 
504
486
  /**
505
- * T3n Client - Main SDK class
487
+ * T3n Client — thin host-function provider + WASM sequencer.
488
+ *
489
+ * The SDK communicates with the session contract strictly through
490
+ * WIT:
491
+ * - Calls `clientHandshake.run(sid)` — contract handles ML-KEM
492
+ * encapsulation, HKDF, POSTs via `host.transport.postRpc`,
493
+ * derives session keys, returns them.
494
+ * - Calls `clientAuth.runEth(keys, address, ...)` — contract
495
+ * builds the SIWE message, signs via `host.eth-signer.ethSign`,
496
+ * POSTs + parses the Finish response, returns the DID.
497
+ * - For `execute()`, the SDK just encrypts the JSON-RPC payload
498
+ * via `sessionCrypto.encrypt` and POSTs it through its transport.
506
499
  *
507
- * Provides a simple interface for establishing secure sessions with T3n nodes.
508
- * All cryptographic complexity is handled in WASM components.
500
+ * No SIWE building, no HKDF, no hex/base64 shuffling, no wire
501
+ * envelopes outside the contract. The contract is the single source
502
+ * of protocol truth.
509
503
  */
510
504
 
511
- /**
512
- * Main T3n SDK Client
513
- */
514
505
  declare class T3nClient {
515
506
  private readonly config;
516
507
  private readonly transport;
517
508
  private readonly sessionId;
518
509
  private readonly logger;
519
- private readonly encryption;
520
510
  private status;
521
- private wasmState;
511
+ private sessionKeys;
522
512
  private did;
523
- private handshakeResult;
524
513
  constructor(config: T3nClientConfig);
525
- /**
526
- * Start the handshake process with the T3n node
527
- */
528
514
  handshake(): Promise<HandshakeResult>;
529
- /**
530
- * Authenticate with the T3n node.
531
- *
532
- * For OIDC, this runs a two-step nonce-bound flow:
533
- * 1. Sends `InitOidcAuth` to server → receives session-binding nonce.
534
- * 2. Calls `getIdToken(nonce)` callback so the app can include the
535
- * nonce in the Google authorization URL.
536
- * 3. Sends `SubmitIdToken` with the nonce-bearing token → receives DID.
537
- */
538
515
  authenticate(authInput: AuthInput): Promise<Did>;
539
- /**
540
- * OIDC two-step authentication with session-binding nonce.
541
- *
542
- * Bypasses the WASM client state machine and makes two encrypted
543
- * RPC calls directly:
544
- * 1. `InitOidcAuth { provider }` → server generates nonce → returns
545
- * `ProvideNonce { nonce }`.
546
- * 2. App calls `getIdToken(nonce)` to obtain a nonce-bound `id_token`.
547
- * 3. `SubmitIdToken { id_token }` → server verifies token + nonce →
548
- * returns `Finish { did }`.
549
- */
550
- private authenticateOidc;
551
- /**
552
- * Execute an action on the T3n node
553
- */
554
516
  execute(payload: unknown): Promise<string>;
555
517
  getSessionId(): SessionId;
556
518
  getStatus(): SessionStatus;
557
519
  getDid(): Did | null;
520
+ isAuthenticated(): boolean;
558
521
  getLastSetCookie(): string | null;
559
522
  getLastResponseHeaders(): Record<string, string>;
560
- isAuthenticated(): boolean;
561
- /**
562
- * Run a WASM state machine flow to completion
563
- */
564
- private runFlow;
565
523
  /**
566
- * Try to finalize the current flow
567
- */
568
- private tryFinalize;
569
- /**
570
- * Handle a WASM request based on its type
571
- */
572
- private handleWasmRequest;
573
- /**
574
- * Handle a send-remote request by calling the RPC endpoint
575
- */
576
- private handleSendRemote;
577
- private captureHandshakeResult;
578
- /**
579
- * Handle a guest-to-host request using configured handlers
580
- */
581
- private handleGuestToHost;
582
- /**
583
- * Send an RPC request with automatic encryption/decryption
584
- */
585
- private sendRpcRequest;
586
- /**
587
- * Get the current session state for encryption
524
+ * Build the `host.transport.postRpc` callback the contract uses for
525
+ * all its HTTP round-trips. Must be passed into `loadWasmComponent`
526
+ * at instantiation time so the contract can POST during handshake
527
+ * and auth.
528
+ *
529
+ * `params` from the contract is the opaque JSON-RPC params (already
530
+ * encrypted where encryption is needed). The SDK wraps in the
531
+ * JSON-RPC envelope and injects the Session-Id header.
588
532
  */
589
- private getSessionState;
533
+ buildPostRpcHostImport(): (method: string, _sessionIdFromGuest: string, params: string) => Promise<string>;
534
+ private sendRpcRaw;
590
535
  }
591
536
 
592
- /**
593
- * Guest-to-Host Request Handlers
594
- *
595
- * These handle requests from WASM that need the host environment to perform side effects.
596
- * Examples: signing challenges, providing public keys, generating random bytes.
597
- */
598
-
599
- /**
600
- * Account — MetaMask handler accepts either a plain address string or an
601
- * object with an `address` field (for compatibility with various wallet
602
- * libraries).
603
- */
604
- type EthAccount = string | {
605
- address: string;
606
- };
607
- /**
608
- * Create an EthSign handler using MetaMask (window.ethereum)
609
- * @param account - MetaMask account (string address or object with address property)
610
- * @param logger - Optional logger instance. Defaults to a logger using the global log level (LogLevel.ERROR).
611
- * Pass a custom logger to override logging behavior for this handler.
612
- * @param privateKey - Optional private key for signing (if provided, MetaMask is not used)
613
- */
614
- declare function metamask_sign(account: EthAccount, logger?: Logger, privateKey?: string | undefined): GuestToHostHandler;
615
- /**
616
- * Get the current MetaMask address
617
- * @returns Ethereum address (lowercase, 0x prefixed)
618
- */
619
- declare function metamask_get_address(): Promise<string>;
620
- /**
621
- * Get the address for a given private key
622
- * @param privateKey - Ethereum private key (0x prefixed hex string)
623
- * @returns Ethereum address (lowercase, 0x prefixed)
624
- */
625
- declare function eth_get_address(privateKey: string): string;
626
- /**
627
- * Create an MlKemPublicKey handler that lazily fetches the root public key
628
- * from `${baseUrl}/status` on first invocation and caches the encoded
629
- * response for subsequent calls.
630
- *
631
- * @param baseUrl - **Required**. The node URL whose `/status` endpoint should
632
- * serve the ML-KEM public key. Must be the same URL the
633
- * T3nClient is constructed with — otherwise the handshake
634
- * encrypts to one node and sends ciphertext to another.
635
- *
636
- * Was optional in 0.3.x, where omitting it caused the lazy
637
- * fetch to silently fall back to `NODE_URLS[currentEnv]` and
638
- * hit the wrong node. Three downstream consumers (demo.ts,
639
- * t3-apps dev wallet hooks, t3n-mcp session manager) all
640
- * hit this trap before we tightened the type.
641
- */
642
- declare function createMlKemPublicKeyHandler(baseUrl: string): GuestToHostHandler;
643
- /**
644
- * Create Random handler backed by crypto.getRandomValues
645
- * Note: The Rust Vec<u8> type serializes as an array of bytes, not a base64 string
646
- */
647
- declare function createRandomHandler(): GuestToHostHandler;
648
- /**
649
- * Create the default handler set required by the T3n handshake.
650
- *
651
- * @param baseUrl - **Required**. Forwarded to `createMlKemPublicKeyHandler`
652
- * so the lazy /status fetch hits the right node.
653
- */
654
- declare function createDefaultHandlers(baseUrl: string): GuestToHostHandlers;
655
-
656
537
  /**
657
538
  * Cryptographic utilities for T3n SDK
658
539
  *
@@ -789,6 +670,65 @@ interface ConfigValidationResult {
789
670
  errors: string[];
790
671
  }
791
672
 
673
+ /**
674
+ * TDX quote verifier backed by the Rust `signature` crate compiled to
675
+ * WASM. Full cryptographic verification: ECDSA P-256 attestation-key
676
+ * signature, PCK certificate chain walk to Intel's root CA, and
677
+ * report_data + RTMR comparison.
678
+ *
679
+ * The WASM bytes are inlined as base64 (see quote_verifier_bytes.ts)
680
+ * so the SDK works without bundler WASM plugins and without runtime
681
+ * asset URL resolution.
682
+ */
683
+ interface QuoteVerifyResult {
684
+ valid: boolean;
685
+ error?: string;
686
+ rtmr3?: string;
687
+ report_data?: string;
688
+ }
689
+ interface PeerQuoteResult {
690
+ peer_id: string;
691
+ valid: boolean;
692
+ error?: string;
693
+ rtmr3?: string;
694
+ }
695
+ interface DkgVerifyResult {
696
+ valid: boolean;
697
+ results: PeerQuoteResult[];
698
+ valid_count: number;
699
+ expected_count: number;
700
+ error?: string;
701
+ }
702
+ /**
703
+ * Verify a single TDX attestation quote with full cryptographic verification.
704
+ *
705
+ * @param quoteB64 - Base64-encoded raw TDX v4 quote
706
+ * @param attestationMsgB64 - Base64-encoded attestation message
707
+ * (for DKG: encaps_key || sorted_peer_id_bytes)
708
+ * @param expectedRtmr3B64 - Optional base64-encoded 48-byte RTMR3
709
+ * @returns Verification result with extracted measurements
710
+ */
711
+ declare function verifyTdxQuote(quoteB64: string, attestationMsgB64: string, expectedRtmr3B64?: string): Promise<QuoteVerifyResult>;
712
+ /**
713
+ * Verify a full DKG attestation bundle: multiple TDX quotes from all
714
+ * participating nodes, plus the binding between the quotes and the
715
+ * ML-KEM encapsulation key. Checks:
716
+ * 1. attestationMsg starts with encapsKey (server can't swap the key)
717
+ * 2. Every quote's ECDSA signature chains to Intel's SGX root CA
718
+ * 3. Every quote's report_data == keccak512(attestationMsg)
719
+ * 4. Optional RTMR3 pinning per quote
720
+ *
721
+ * @param encapsKeyB64 - Base64-encoded ML-KEM encapsulation key
722
+ * (from `/status.encaps_key`)
723
+ * @param attestationMsgB64 - Base64-encoded raw attestation message
724
+ * (from `/status.dkg_attestation.attestation_msg`)
725
+ * @param peerIds - Sorted array of base58 peer IDs
726
+ * @param quotes - Map of peer_id → base64-encoded TDX quote
727
+ * @param expectedRtmr3B64 - Optional base64-encoded 48-byte RTMR3
728
+ * @returns Per-peer verification results and overall validity
729
+ */
730
+ declare function verifyDkgAttestation(encapsKeyB64: string, attestationMsgB64: string, peerIds: string[], quotes: Record<string, string>, expectedRtmr3B64?: string): Promise<DkgVerifyResult>;
731
+
792
732
  /**
793
733
  * Configuration validation for T3n SDK
794
734
  */
@@ -812,6 +752,18 @@ declare function validateConfig(config: unknown): ConfigValidationResult;
812
752
  * or by passing `baseUrl` to `T3nClient`.
813
753
  */
814
754
  declare const NODE_URLS: Record<Environment, string>;
755
+ /** DKG attestation bundle from the cluster. */
756
+ interface DkgAttestation {
757
+ /** Sorted base58 peer IDs that participated in DKG. */
758
+ peer_ids: string[];
759
+ /** Per-node TDX quotes keyed by base58 peer ID (base64-encoded). */
760
+ quotes: Record<string, string>;
761
+ /**
762
+ * Base64-encoded raw attestation message: `encaps_key || sorted_peer_ids`.
763
+ * Each quote's `report_data` is `keccak512(attestation_msg)`.
764
+ */
765
+ attestation_msg: string;
766
+ }
815
767
  /**
816
768
  * Set the active environment. Clears any previous URL override and the key
817
769
  * cache so the next fetch uses the new environment's default URL.
@@ -832,10 +784,30 @@ declare function setNodeUrl(url: string | null): void;
832
784
  /** Resolve the active node URL: explicit `baseUrl` > override > env default. */
833
785
  declare function getNodeUrl(baseUrl?: string): string;
834
786
  /**
835
- * Fetch the ML-KEM root public key from `${nodeUrl}/status`. Cached per URL.
836
- * The node must be in the `Ready` phase and expose `encaps_key`.
787
+ * Fetch the ML-KEM root public key from `${nodeUrl}/status`. Cached
788
+ * per URL because the key is stable for the cluster's lifetime (a
789
+ * new DKG means a full redeploy; callers clear the cache via
790
+ * `clearKeyCache()` or `setNodeUrl()` in that case).
791
+ *
792
+ * Returns only the base64-encoded key. For the DKG attestation
793
+ * bundle (which changes over time as peer quotes replicate via
794
+ * Raft), call `fetchDkgAttestation()` \u2014 that path is
795
+ * intentionally uncached.
837
796
  */
838
797
  declare function fetchMlKemPublicKey(baseUrl?: string): Promise<string>;
798
+ /**
799
+ * Fetch the DKG attestation bundle from `${nodeUrl}/status`. Never
800
+ * cached \u2014 peer quotes are written to consensus KV asynchronously
801
+ * during cluster bootstrap, so early reads may see a subset of the
802
+ * expected quotes. Caching would pin an incomplete bundle and cause
803
+ * spurious `valid_count < expected_count` failures in
804
+ * `verifyDkgAttestation()` for the whole process lifetime.
805
+ *
806
+ * Returns `undefined` when the node has not yet published an
807
+ * attestation (e.g. still bootstrapping, or running with a mock
808
+ * signer where attestation is skipped by design).
809
+ */
810
+ declare function fetchDkgAttestation(baseUrl?: string): Promise<DkgAttestation | undefined>;
839
811
  /** Clear the cached ML-KEM public keys. Useful in tests. */
840
812
  declare function clearKeyCache(): void;
841
813
  /**
@@ -845,5 +817,5 @@ declare function clearKeyCache(): void;
845
817
  */
846
818
  declare function loadConfig(baseUrl?: string): SdkConfig;
847
819
 
848
- export { AuthMethod, AuthenticationError, HandshakeError, HttpTransport, LogLevel, MockTransport, NODE_URLS, RpcError, SessionStateError, SessionStatus, T3nClient, T3nError, WasmError, bytesToString, clearKeyCache, createDefaultHandlers, createEthAuthInput, createLogger, createMlKemPublicKeyHandler, createOidcAuthInput, createRandomHandler, decodeWasmErrorMessage, eth_get_address, extractWasmError, fetchMlKemPublicKey, generateRandomString, generateUUID, getEnvironment, getEnvironmentName, getGlobalLogLevel, getLogger, getNodeUrl, getScriptVersion, loadConfig, loadWasmComponent, metamask_get_address, metamask_sign, redactSecrets, redactSecretsFromJson, setEnvironment, setGlobalLogLevel, setNodeUrl, stringToBytes, validateConfig };
849
- export type { AuthInput, ClientAuth, ClientHandshake, ConfigValidationResult, Did, Environment, EthAuthInput, GuestToHostHandler, GuestToHostHandlers, HandshakeResult, JsonRpcRequest, JsonRpcResponse, Logger, OidcAuthInput, OidcCredentials, SdkConfig, SessionCrypto, SessionId, T3nClientConfig, Transport, WasmComponent, WasmNextResult };
820
+ export { AuthMethod, AuthenticationError, HandshakeError, HttpTransport, LogLevel, MockTransport, NODE_URLS, RpcError, SessionStateError, SessionStatus, T3nClient, T3nError, WasmError, bytesToString, clearKeyCache, createEthAuthInput, createLogger, createOidcAuthInput, decodeWasmErrorMessage, extractWasmError, fetchDkgAttestation, fetchMlKemPublicKey, generateRandomString, generateUUID, getEnvironment, getEnvironmentName, getGlobalLogLevel, getLogger, getNodeUrl, getScriptVersion, loadConfig, loadWasmComponent, redactSecrets, redactSecretsFromJson, setEnvironment, setGlobalLogLevel, setNodeUrl, stringToBytes, validateConfig, verifyDkgAttestation, verifyTdxQuote };
821
+ export type { AuthInput, AuthOutcome, ClientAuth, ClientHandshake, ClientSessionKeys, ConfigValidationResult, CookieIface, Did, DkgAttestation, DkgVerifyResult, Environment, EthAuthInput, HandshakeOutcome, HandshakeResult, JsonRpcRequest, JsonRpcResponse, Logger, OidcAuthInput, OidcCredentials, PeerQuoteResult, QuoteVerifyResult, SdkConfig, ServerHandshake, ServerOutcome, ServerSessionKeys, SessionCrypto, SessionHostImports, SessionId, T3nClientConfig, Transport, Validation, WasmComponent };