tisura-light 0.0.1-100

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 (38) hide show
  1. package/README.md +176 -0
  2. package/dist/certify/embedCertificateEml.d.ts +21 -0
  3. package/dist/certify/embedCertificatePdf.d.ts +23 -0
  4. package/dist/certify/embedQrCode.d.ts +27 -0
  5. package/dist/certify/findBestQrPlacement.d.ts +13 -0
  6. package/dist/certify/utils.d.ts +5 -0
  7. package/dist/client-light.d.ts +110 -0
  8. package/dist/config.d.ts +13 -0
  9. package/dist/connect/connect.d.ts +81 -0
  10. package/dist/connect/ftp/ftpClient.d.ts +18 -0
  11. package/dist/connect/index.d.ts +67 -0
  12. package/dist/connect/internal/connectionContext.d.ts +50 -0
  13. package/dist/connect/internal/fileTypes.d.ts +3 -0
  14. package/dist/connect/internal/httpRequest.d.ts +57 -0
  15. package/dist/connect/internal/httpStatus.d.ts +6 -0
  16. package/dist/connect/internal/tlsSession.d.ts +6 -0
  17. package/dist/connect/internal/tokenize.d.ts +6 -0
  18. package/dist/connect/internal/tunnel.d.ts +15 -0
  19. package/dist/connect/tls/index.d.ts +20 -0
  20. package/dist/connect/tls/wasm/tls.d.ts +148 -0
  21. package/dist/connect/tls/wasm/tls.js +758 -0
  22. package/dist/connect/tls/wasm/tls_bg.wasm +0 -0
  23. package/dist/connect/tls/wasm/tls_bg.wasm.d.ts +32 -0
  24. package/dist/index.js +83325 -0
  25. package/dist/index.light.d.ts +11 -0
  26. package/dist/inputs.d.ts +101 -0
  27. package/dist/metrics.d.ts +13 -0
  28. package/dist/parse/fetcher.d.ts +7 -0
  29. package/dist/parse/index.d.ts +12 -0
  30. package/dist/parse/parser.d.ts +14 -0
  31. package/dist/parse/types.d.ts +31 -0
  32. package/dist/tls13.d.ts +32 -0
  33. package/dist/tls_bg.wasm +0 -0
  34. package/dist/types.d.ts +6 -0
  35. package/dist/utils.d.ts +12 -0
  36. package/dist/verify/ftps.d.ts +32 -0
  37. package/package.json +99 -0
  38. package/public/.gitkeep +0 -0
package/README.md ADDED
@@ -0,0 +1,176 @@
1
+ # Sentinel SDK
2
+
3
+ This project contains the code for [tisura](https://www.npmjs.com/package/tisura) npm package.
4
+ It provides modules for parsing network packets, proving statements, managing connections, and handling TLS operations.
5
+
6
+ ## Build
7
+
8
+ ### Build Wasm files
9
+
10
+ Make sure to use `rustc` version of `1.82.0`.
11
+
12
+ To install it, you can run:
13
+
14
+ ```bash
15
+ # first install rustup
16
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
17
+ # then install rust
18
+ rustup install 1.82.0
19
+ rustup default 1.82.0
20
+ ```
21
+
22
+ ### Build Noir files
23
+
24
+ Make sure to install `noir`.
25
+
26
+ To install it, you can run:
27
+
28
+ ```bash
29
+ # first install noirup
30
+ curl -L https://raw.githubusercontent.com/noir-lang/noirup/refs/heads/main/install | bash
31
+ # then install noir
32
+ noirup --version 1.0.0-beta.6
33
+ ```
34
+
35
+ ## Local SDK Development
36
+
37
+ The `build-and-install.sh` script builds the SDK as a `.tgz` (exactly as it would be published to npm) and installs it into a sibling consumer project.
38
+
39
+ ```bash
40
+ ./build-and-install.sh <mode> <dest>
41
+ ```
42
+
43
+ - **`<mode>`** (optional, default `full`): `full` builds with WASM + TS, `light` produces a slim ESM bundle (no TLS/circuit code, just stamping + provider requests).
44
+ - **`<dest>`** (optional, default `twallet`): one of `extension`, `platform`, `airdrop`, `twallet`, `explorer`. `platform` and `airdrop` are installed via `yarn`, the others via `npm`.
45
+
46
+ The script removes any existing `tisura*.tgz` and `node_modules/tisura` in the destination, clears the package manager's cache for tisura, and force-installs the new tarball — so re-running with the same version reliably picks up the new SDK code.
47
+
48
+ Examples:
49
+
50
+ ```bash
51
+ ./build-and-install.sh # full build → twallet (npm)
52
+ ./build-and-install.sh light extension # light build → sentinel_extension (npm)
53
+ ./build-and-install.sh full platform # full build → sentinel/platform (yarn)
54
+ ```
55
+
56
+ ## Installation
57
+
58
+ ```bash
59
+ npm install tisura
60
+ ```
61
+
62
+ ## Usage
63
+
64
+ ### Basic Setup
65
+
66
+ ```typescript
67
+ import { Tisura } from "tisura";
68
+
69
+ const client = new Tisura({
70
+ apiKey: "your-api-key", // Format: sk_dev_xxx key, sk_prod_xxx key, or simply sk_local for local development
71
+ });
72
+ ```
73
+
74
+ ### Sending a request to the server
75
+
76
+ ```typescript
77
+ const connectClient = client.connect;
78
+
79
+ const conn = await connectClient.sendRequest({
80
+ serverHost, // e.g. "api.github.com"
81
+ serverPort, // e.g. 443
82
+ endpoint, // e.g. "/users"
83
+ params, // e.g. [{ key: "since", value: "1" }]
84
+ method, // e.g. "POST"
85
+ body , // eg. [{ key: "name", value: "sherlock" }] - Optional
86
+ headers, // e.g. { key: "Authorization", value: `Bearer ${token}` } - Optional
87
+ }: SendRequestArgs);
88
+ ```
89
+
90
+ ### Generating a proof and verifying it
91
+
92
+ ```typescript
93
+ const proveClient = client.prove;
94
+
95
+ const proof = await proveClient.generateProof({
96
+ circuitName, // e.g. "ownership"
97
+ connectionId, // optional, defaults to the last connection
98
+ plaintext, // the data you want to prove in "substring" circuit - Optional
99
+ nodeId, // the github node ID to prove in "ownership" circuit - Optional
100
+ repoName, // the github repo name to prove in "contributions" circuit - Optional
101
+ repoOwner, // the github repo owner to prove in "contributions" circuit - Optional
102
+ count, // the number of contributions to prove in "contributions" circuit - Optional
103
+ }: GenerateProofArgs);
104
+
105
+ const isValid = await proveClient.verifyProof({
106
+ circuitName, // e.g. "ownership"
107
+ proof, // the proof above
108
+ }: VerifyProofArgs);
109
+ ```
110
+
111
+ ### Certifying a statement
112
+
113
+ ```typescript
114
+ const certifyClient = client.certify;
115
+
116
+ const cert = await certifyClient.certify({
117
+ inputBytes, // the data you want to certify (in bytes)
118
+ connectionId, // optional, defaults to the last connection
119
+ inputSessionKey, // optional, defaults to the last session key
120
+ }: CertifyArgs)
121
+ ```
122
+
123
+ ### Decrypting an encrypted statement
124
+
125
+ ```typescript
126
+ const certifyClient = client.certify;
127
+ const decrypted = await certifyClient.decrypt({
128
+ connectionId, // optional, defaults to the last connection
129
+ }: DecryptArgs);
130
+ ```
131
+
132
+ ### Available Modules
133
+
134
+ The SDK consists of several modules:
135
+
136
+ - **Parse**: Network packet parsing and analysis
137
+ - **Prove**: Statement proving and verification
138
+ - **Certify**: Statement certifying from client side
139
+ - **Connect**: Connection management
140
+
141
+ ### Module-specific Imports
142
+
143
+ You can import specific modules directly:
144
+
145
+ ```typescript
146
+ import { ParseClient } from "tisura/parse";
147
+ import { ProveClient } from "tisura/prove";
148
+ import { CertifyClient } from "tisura/certify";
149
+ import { ConnectClient } from "tisura/connect";
150
+ ```
151
+
152
+ ## Configuration
153
+
154
+ The SDK requires the following configuration parameters:
155
+
156
+ ```typescript
157
+ interface TisuraConfig {
158
+ proxyUrl: string;
159
+ storeUrl: string;
160
+ }
161
+ ```
162
+
163
+ ## Development
164
+
165
+ ### Install, build and run tests
166
+
167
+ ```bash
168
+ # Install dependencies
169
+ npm install
170
+
171
+ # Build the package
172
+ npm run build
173
+
174
+ # Run tests
175
+ npm test
176
+ ```
@@ -0,0 +1,21 @@
1
+ import { SessionKey } from "../inputs.js";
2
+ /**
3
+ * Embed certificate.json as a folded `X-Tisura-Certificate` header (RFC 5322).
4
+ *
5
+ * The cert JSON is base64-encoded and inserted right before the header/body
6
+ * separator. Body bytes are preserved byte-identical, and the original `.eml`
7
+ * is recoverable by stripping the inserted header.
8
+ */
9
+ export declare function embedCertificateInEml(originalEmlBytes: Uint8Array, certificate: SessionKey): {
10
+ stampedEmlBytes: Uint8Array;
11
+ };
12
+ /**
13
+ * Extract the embedded certificate from a stamped `.eml` and return the
14
+ * recovered original bytes (with the `X-Tisura-Certificate` header stripped).
15
+ * Returns null if no embedded certificate is found.
16
+ */
17
+ export declare function extractCertificateFromEml(emlBytes: Uint8Array): {
18
+ certObj: unknown;
19
+ originalEmlBytes: Uint8Array;
20
+ } | null;
21
+ export declare function isEmlWithCertificate(emlBytes: Uint8Array): boolean;
@@ -0,0 +1,23 @@
1
+ import { SessionKey } from "../inputs.js";
2
+ /**
3
+ * Embed certificate.json as a PDF file attachment (ISO 32000-2:2020, 7.11.4).
4
+ *
5
+ * Uses incremental save to preserve original bytes as a prefix of the stamped
6
+ * PDF. The certificate includes `original_content_length` so the verifier can
7
+ * slice the stamped PDF to recover the exact original bytes and compare them
8
+ * against the TLS-decrypted body.
9
+ */
10
+ export declare function embedCertificateInPdf(originalPdfBytes: Uint8Array, certificate: SessionKey): Promise<{
11
+ stampedPdfBytes: Uint8Array;
12
+ }>;
13
+ /**
14
+ * Extract certificate.json from a PDF's EmbeddedFiles name tree.
15
+ * Returns null if no embedded certificate is found.
16
+ */
17
+ export declare function extractCertificateFromPdf(pdfBytes: Uint8Array): Promise<{
18
+ certObj: unknown;
19
+ } | null>;
20
+ /**
21
+ * Check if a PDF has an embedded certificate attachment.
22
+ */
23
+ export declare function isPdfWithCertificate(pdfBytes: Uint8Array): Promise<boolean>;
@@ -0,0 +1,27 @@
1
+ import { SessionKey } from "../inputs.js";
2
+ export type QrPlacement = {
3
+ pageIndex: number;
4
+ x: number;
5
+ y: number;
6
+ size?: number;
7
+ };
8
+ /**
9
+ * Embed a QR code on the PDF.
10
+ *
11
+ * Defaults to bottom-right of the last page. Pass `placement` to override —
12
+ * callers that detect whitespace can pick a corner that won't collide with
13
+ * existing content.
14
+ *
15
+ * The QR encodes a verification URL with certificate query params:
16
+ * <verifyBaseUrl>?cr=<client_random>&secret=<secret>&len=<original_content_length>
17
+ *
18
+ * Uses QRCode.toCanvas with OffscreenCanvas in service workers (no DOM needed),
19
+ * falls back to QRCode.toDataURL in Node.js.
20
+ *
21
+ * Uses incremental save to preserve all preceding bytes (including any
22
+ * certificate attachment from embedCertificateInPdf) as a prefix of the
23
+ * output, so `original_content_length` slice still works for verification.
24
+ */
25
+ export declare function embedQrCodeInPdf(pdfBytes: Uint8Array, certificate: SessionKey & {
26
+ original_content_length: number;
27
+ }, verifyBaseUrl?: string, placement?: QrPlacement): Promise<Uint8Array>;
@@ -0,0 +1,13 @@
1
+ import type { QrPlacement } from "./embedQrCode.js";
2
+ /**
3
+ * Pick the brightest whitespace spot inside any of the four corner regions
4
+ * of the last page so a QR stamp avoids both page-edge content (decorative
5
+ * borders) and the page interior (body text).
6
+ *
7
+ * For each corner, slides a (qrSize + 2·margin)² probe and picks the
8
+ * position with the highest mean luminance across all four corners.
9
+ *
10
+ * Coordinates are returned in PDF user space (origin at bottom-left), ready
11
+ * to hand to embedQrCodeInPdf.
12
+ */
13
+ export declare function findBestQrPlacement(pdfBytes: Uint8Array, qrSize?: number, margin?: number, cornerSize?: number): Promise<QrPlacement>;
@@ -0,0 +1,5 @@
1
+ export declare function concatUint8Arrays(arrays: Uint8Array[]): Uint8Array;
2
+ export declare function decodeToBytes(input: string | ArrayBuffer | Uint8Array): Uint8Array;
3
+ export declare function includes(source: Uint8Array, needle: Uint8Array): boolean;
4
+ export declare function bytesToBase64(bytes: Uint8Array): string;
5
+ export declare function extractPdfFromEnvelope(body: Uint8Array): Uint8Array | null;
@@ -0,0 +1,110 @@
1
+ import { TisuraConfig } from "./config.js";
2
+ import { ConnectClient } from "./connect/index.js";
3
+ import { SessionKey, LinkedSessionCertificate } from "./inputs.js";
4
+ import { FtpsVerification, VerifyFtpsOptions } from "./verify/ftps.js";
5
+ export type SendRequestArgs = {
6
+ serverHost: string;
7
+ endpoint: string;
8
+ method: "GET" | "POST";
9
+ params?: Array<{
10
+ key: string;
11
+ value: string;
12
+ }>;
13
+ body?: Array<{
14
+ key: string;
15
+ value: string;
16
+ }>;
17
+ headers?: Array<{
18
+ key: string;
19
+ value: string;
20
+ }>;
21
+ serverPort?: number;
22
+ onProgress?: (...args: [number, number?]) => void;
23
+ };
24
+ export type SendProviderRequestArgs = {
25
+ providerKey: string;
26
+ providerContext?: unknown;
27
+ headers?: Array<{
28
+ key: string;
29
+ value: string;
30
+ }>;
31
+ onProgress?: (...args: [number, number?]) => void;
32
+ };
33
+ export type ProviderInfo = {
34
+ id: string;
35
+ responseStatus: boolean;
36
+ };
37
+ export type DownloadFtpsArgs = {
38
+ serverHost: string;
39
+ user: string;
40
+ pass: string;
41
+ remotePath: string;
42
+ };
43
+ export declare class TisuraLight {
44
+ config: TisuraConfig;
45
+ protected connectClient: ConnectClient;
46
+ constructor({ apiKey }: {
47
+ apiKey: string;
48
+ });
49
+ sendRequest(args: SendRequestArgs): Promise<string | Blob>;
50
+ sendRequestRawResponse({ serverHost, endpoint, params, method, body, headers, serverPort, onProgress, }: SendRequestArgs): Promise<Uint8Array>;
51
+ /**
52
+ * Sends a request expected to return a PDF and returns the raw PDF bytes
53
+ * along with the TLS session key captured from the connection.
54
+ *
55
+ * Use this when you want to run logic between fetch and stamping (for
56
+ * example, scanning the PDF for whitespace before placing the QR). For the
57
+ * common case, prefer `sendRequestAndStampPdf`.
58
+ *
59
+ * Throws if the response is not application/pdf or if no
60
+ * SERVER_TRAFFIC_SECRET_0 key was captured.
61
+ */
62
+ sendRequestForPdf(args: SendRequestArgs): Promise<{
63
+ pdfBytes: Uint8Array;
64
+ sessionKey: SessionKey;
65
+ }>;
66
+ /**
67
+ * Sends a request expected to return a PDF and stamps a Tisura verification
68
+ * QR code in the bottom-right of the last page. The QR encodes the
69
+ * environment-aware verifyBaseUrl plus the TLS session key from this
70
+ * connection, so the recipient can verify the PDF's authenticity.
71
+ *
72
+ * Reads the session key directly from the connection's in-memory buffer, so
73
+ * this works in any runtime including Node — no localStorage required.
74
+ *
75
+ * Returns the QR-stamped PDF as a Uint8Array. Throws if the response is not
76
+ * application/pdf or if no SERVER_TRAFFIC_SECRET_0 key was captured.
77
+ */
78
+ sendRequestAndStampPdf(args: SendRequestArgs): Promise<Uint8Array>;
79
+ sendProviderRequest(args: SendProviderRequestArgs): Promise<string | Blob>;
80
+ sendProviderRequestRawResponse({ providerKey, providerContext, headers, onProgress, }: SendProviderRequestArgs): Promise<Uint8Array>;
81
+ /**
82
+ * POC: download a single file over implicit FTPS (port 990) and return just
83
+ * the file bytes. Establishes two tunnels (control + data), each with its own
84
+ * TLS session captured by the proxy.
85
+ */
86
+ downloadFtpsFile(args: DownloadFtpsArgs): Promise<Uint8Array>;
87
+ /**
88
+ * Like {@link downloadFtpsFile}, but also returns a {@link
89
+ * LinkedSessionCertificate} bundling the control- and data-channel TLS keys
90
+ * plus the PASV data endpoint. These are what a verifier needs to bind the
91
+ * two sessions into a single proof ("file F answered the command issued on
92
+ * the control channel"). Verification / the proxy-attested dial-address
93
+ * cross-check is separate (later phases); this surfaces the inputs.
94
+ *
95
+ * Throws if the expected traffic secrets were not captured on either channel.
96
+ */
97
+ downloadFtpsFileWithCertificate({ serverHost, user, pass, remotePath, }: DownloadFtpsArgs): Promise<{
98
+ bytes: Uint8Array;
99
+ certificate: LinkedSessionCertificate;
100
+ }>;
101
+ /**
102
+ * Verifies an FTPS download from its {@link LinkedSessionCertificate}: decrypts
103
+ * the proxy-captured control + data transcripts, checks the proxy-signed dial
104
+ * address of the data session matches the PASV endpoint named on the control
105
+ * channel, and returns the bound claim (command + file).
106
+ */
107
+ verifyFtpsDownload(cert: LinkedSessionCertificate, opts?: VerifyFtpsOptions): Promise<FtpsVerification>;
108
+ updateProviderMetrics({ id, responseStatus, }: ProviderInfo): Promise<void>;
109
+ protected incrementApiKeyCounter(): Promise<void>;
110
+ }
@@ -0,0 +1,13 @@
1
+ export interface TisuraConfig {
2
+ proxyUrl: string;
3
+ storeUrl: string;
4
+ verifyBaseUrl: string;
5
+ apiKey: string;
6
+ proxyPublicKeyHex?: string;
7
+ }
8
+ export declare function deriveConfigFromAPIKey(apiKey: string): TisuraConfig;
9
+ export declare class TisuraBase {
10
+ config: TisuraConfig;
11
+ constructor(config: TisuraConfig);
12
+ protected getStoreFetcherEndpoint(): string;
13
+ }
@@ -0,0 +1,81 @@
1
+ import { TisuraConfig } from "../config.js";
2
+ import { SessionKey } from "../inputs.js";
3
+ import { BuiltRequest } from "./internal/connectionContext.js";
4
+ import { SessionStore } from "./tls/index.js";
5
+ export type ConnectOptions = {
6
+ /** Shared TLS session store to enable resumption (FTPS data channel). */
7
+ sessionStore?: SessionStore;
8
+ /**
9
+ * TLS server name (SNI) for the handshake, when it must differ from the
10
+ * tunnel target host — e.g. a PASV data channel that connects to a bare IP
11
+ * but must resume the control session keyed by its hostname.
12
+ */
13
+ tlsServerName?: string;
14
+ };
15
+ /**
16
+ * Class to create a raw TCP tunnel between the client and the server and upgrade to TLS.
17
+ */
18
+ export declare class Connect {
19
+ private config;
20
+ private tlsClient;
21
+ private serverHost;
22
+ private serverPort;
23
+ private ctx;
24
+ constructor(config: TisuraConfig);
25
+ /**
26
+ * Establishes a secure TLS connection to a target server via a proxy tunnel.
27
+ */
28
+ connectToServer(serverHost: string, serverPort?: number, opts?: ConnectOptions): Promise<void>;
29
+ /**
30
+ * Establishes a secure TLS connection where the proxy builds the request
31
+ * from its stored config for `providerKey`. Returns the built request fields
32
+ * so the caller can use them for the HTTP request sent through the tunnel.
33
+ */
34
+ connectToProviderServer(providerKey: string, providerContext?: unknown): Promise<BuiltRequest>;
35
+ /**
36
+ * Sends a message to the server via the established TLS connection.
37
+ * @param {string} path - The path for the HTTP request
38
+ * @param {Array<{ key: string; value: string }>} params - Query parameters
39
+ * @param {string} method - HTTP method (GET, POST, etc.)
40
+ * @param {Array<{ key: string; value: string }>} body - Request body fields
41
+ * @param {Array<{ key: string; value: string }>} headers - HTTP headers
42
+ * @param {Function} onProgress - Optional progress callback
43
+ * @returns {Promise<Uint8Array>} - The server's response
44
+ */
45
+ sendRequest(path: string, params: Array<{
46
+ key: string;
47
+ value: string;
48
+ }>, method: string, body: Array<{
49
+ key: string;
50
+ value: string;
51
+ }>, headers: Array<{
52
+ key: string;
53
+ value: string;
54
+ }>, onProgress?: (bytesReceived: number, totalBytes?: number) => void): Promise<Uint8Array>;
55
+ /**
56
+ * Registers a callback to receive decrypted TLS application-data bytes,
57
+ * bypassing the HTTP response accumulator. Used by non-HTTP protocols.
58
+ */
59
+ setOnDecryptedData(cb: (data: Uint8Array) => void): void;
60
+ /**
61
+ * Registers a callback fired when the underlying WebSocket closes. Used by
62
+ * non-HTTP protocols whose end-of-stream signal is the socket close.
63
+ */
64
+ setOnClose(cb: () => void): void;
65
+ /**
66
+ * Encrypts and sends raw bytes over the established TLS session. Throws if
67
+ * the handshake has not completed or the connection is not initialized.
68
+ */
69
+ sendEncrypted(data: Uint8Array): void;
70
+ /**
71
+ * Drains and returns the TLS session keys captured during this connection's
72
+ * handshake. Returns [] if the TLS connection is no longer available (e.g.
73
+ * after disconnect). Calling this twice returns [] the second time.
74
+ */
75
+ takeSessionKeys(): SessionKey[];
76
+ /**
77
+ * Disconnects from the server and cleans up resources.
78
+ * Closes the WebSocket connection and resets internal state variables.
79
+ */
80
+ disconnectFromServer(): Promise<void>;
81
+ }
@@ -0,0 +1,18 @@
1
+ import { TisuraConfig } from "../../config.js";
2
+ import { SessionKey } from "../../inputs.js";
3
+ export type FtpsDownloadResult = {
4
+ bytes: Uint8Array;
5
+ controlSessionKeys: SessionKey[];
6
+ dataSessionKeys: SessionKey[];
7
+ pasvAddr: string;
8
+ };
9
+ /**
10
+ * Minimal implicit-FTPS client (port 990) that downloads a single file via
11
+ * two tunnels (control + data). POC scope: USER/PASS auth, binary transfer,
12
+ * passive mode, no explicit AUTH TLS upgrade, no listings, no resume.
13
+ */
14
+ export declare class FtpClient {
15
+ private config;
16
+ constructor(config: TisuraConfig);
17
+ download(host: string, user: string, pass: string, remotePath: string): Promise<FtpsDownloadResult>;
18
+ }
@@ -0,0 +1,67 @@
1
+ import { TisuraBase, TisuraConfig } from "../config.js";
2
+ import { SessionKey } from "../inputs.js";
3
+ type KV = {
4
+ key: string;
5
+ value: string;
6
+ };
7
+ type OnProgress = (bytesReceived: number, totalBytes?: number) => void;
8
+ export type SendRequestOptions = {
9
+ serverHost: string;
10
+ endpoint: string;
11
+ params: KV[];
12
+ method: string;
13
+ body: KV[];
14
+ headers?: KV[];
15
+ serverPort?: number;
16
+ onProgress?: OnProgress;
17
+ maxRedirects?: number;
18
+ };
19
+ export type SendProviderRequestOptions = {
20
+ providerKey: string;
21
+ providerContext?: unknown;
22
+ headers?: KV[];
23
+ onProgress?: OnProgress;
24
+ maxRedirects?: number;
25
+ };
26
+ export declare class ConnectClient extends TisuraBase {
27
+ constructor(config: TisuraConfig);
28
+ /**
29
+ * Establishes a secure TLS connection to the server via a proxy tunnel.
30
+ * Sends a request to the server and waits for a response.
31
+ * Closes the connection after receiving the response.
32
+ * @param onProgress - Optional callback for download progress (bytesReceived, totalBytes)
33
+ */
34
+ sendRequest(opts: SendRequestOptions): Promise<Uint8Array>;
35
+ /**
36
+ * Variant of {@link sendRequest} that also returns the TLS session keys
37
+ * captured during the request. Lets callers (e.g.
38
+ * `sendRequestAndStampPdf`) avoid round-tripping through localStorage.
39
+ * Useful in environments without browser storage, like Node.
40
+ *
41
+ * Redirect semantics: if the request follows redirects, the returned
42
+ * `sessionKeys` are from the **final hop only** — the connection that
43
+ * actually delivered the response. Keys from intermediate hops are
44
+ * discarded with their connections. If you need keys for an intermediate
45
+ * hop, disable redirects (`maxRedirects: 0`) and follow them manually.
46
+ */
47
+ sendRequestWithKeys({ serverHost, endpoint, params, method, body, headers, serverPort, onProgress, maxRedirects, }: SendRequestOptions): Promise<{
48
+ response: Uint8Array;
49
+ sessionKeys: SessionKey[];
50
+ }>;
51
+ /**
52
+ * Sends a request built by the proxy from the provider's stored template.
53
+ */
54
+ sendProviderRequest({ providerKey, providerContext, headers, onProgress, maxRedirects, }: SendProviderRequestOptions): Promise<Uint8Array>;
55
+ private sendHop;
56
+ private withConnection;
57
+ private followRedirects;
58
+ }
59
+ /**
60
+ * Process the complete response after all data has been received.
61
+ */
62
+ export declare function extractHeadersAndBodyFromFullResponse(fullData: Uint8Array): {
63
+ body: Uint8Array;
64
+ headers: Record<string, string>;
65
+ };
66
+ export declare function processCompleteResponse(data: Uint8Array): string | Blob;
67
+ export {};
@@ -0,0 +1,50 @@
1
+ import { TlsConnection } from "../tls/wasm/tls.js";
2
+ export type BuiltRequest = {
3
+ serverHost: string;
4
+ serverPort?: number;
5
+ method: string;
6
+ endpoint: string;
7
+ params: Array<{
8
+ key: string;
9
+ value: string;
10
+ }>;
11
+ headers: Array<{
12
+ key: string;
13
+ value: string;
14
+ }>;
15
+ body?: unknown;
16
+ };
17
+ /**
18
+ * Holds all state for a single connection instance.
19
+ * Eliminates global state by encapsulating WebSocket, TLS, and response tracking.
20
+ */
21
+ export declare class ConnectionContext {
22
+ ws: WebSocket | null;
23
+ isTunnelEstablished: boolean;
24
+ tlsConnection: TlsConnection | undefined;
25
+ hasTlsSessionStarted: boolean;
26
+ hasCompletedHandshake: boolean;
27
+ hasCompletedSession: boolean;
28
+ wasmInitialized: boolean;
29
+ pendingResponse: ResponseAccumulator | null;
30
+ onDecryptedData?: (data: Uint8Array) => void;
31
+ onClose?: () => void;
32
+ /**
33
+ * Clean up all resources for this connection
34
+ */
35
+ cleanup(): void;
36
+ }
37
+ /**
38
+ * Type definition for response tracking
39
+ */
40
+ export interface ResponseAccumulator {
41
+ buffer: Uint8Array;
42
+ isComplete: boolean;
43
+ resolve: (value: Uint8Array) => void;
44
+ reject: (reason: any) => void;
45
+ absoluteTimeout: ReturnType<typeof setTimeout>;
46
+ idleTimeout: ReturnType<typeof setTimeout>;
47
+ startTime: number;
48
+ onProgress?: (bytesReceived: number, totalBytes?: number) => void;
49
+ contentLength?: number;
50
+ }
@@ -0,0 +1,3 @@
1
+ export declare function normalizeMimeType(contentType: string): string;
2
+ export declare const FILE_TYPE_MAP: Record<string, string>;
3
+ export declare const BINARY_PREFIXES: string[];
@@ -0,0 +1,57 @@
1
+ import { ConnectionContext } from "./connectionContext.js";
2
+ /**
3
+ * Create the HTTP request, encrypt it and send it to the server.
4
+ */
5
+ export declare function createAndEncryptHttpRequest(ctx: ConnectionContext, serverHost: string, path: string, params: Array<{
6
+ key: string;
7
+ value: string;
8
+ }>, method: string, body: Array<{
9
+ key: string;
10
+ value: string;
11
+ }>, headers: Array<{
12
+ key: string;
13
+ value: string;
14
+ }>, serverPort?: number): Uint8Array;
15
+ /**
16
+ * Create the HTTP request.
17
+ */
18
+ export declare function createHttpRequest(serverHost: string, path: string, params: Array<{
19
+ key: string;
20
+ value: string;
21
+ }>, method: string, body: Array<{
22
+ key: string;
23
+ value: string;
24
+ }>, extraHeaders: Array<{
25
+ key: string;
26
+ value: string;
27
+ }>, serverPort?: number): string;
28
+ /**
29
+ * Handles the server response received over the TLS connection.
30
+ */
31
+ export declare function handleServerResponse(ctx: ConnectionContext, onProgress?: (bytesReceived: number, totalBytes?: number) => void): Promise<Uint8Array>;
32
+ /**
33
+ * Called by TLS layer to notify HTTP layer of new data.
34
+ */
35
+ export declare function notifyTlsDataReceived(ctx: ConnectionContext, data: Uint8Array): void;
36
+ export declare function parseHeaders(headerText: string): Record<string, string>;
37
+ export declare function isChunkedBodyComplete(body: Uint8Array): boolean;
38
+ export declare function parseChunkedBody(body: Uint8Array): Uint8Array;
39
+ /**
40
+ * Gets appropriate MIME type and file type for binary content
41
+ */
42
+ export declare function getBinaryContentInfo(contentType: string, headers: Record<string, string>): {
43
+ mimeType: string;
44
+ fileType: string;
45
+ };
46
+ export declare function handleContentType(bodyBytes: Uint8Array, headers: Record<string, string>): string | Blob;
47
+ /**
48
+ * Split the headers and body of the HTTP response.
49
+ */
50
+ export declare function splitHeadersAndBody(data: Uint8Array): {
51
+ headers: string;
52
+ body: Uint8Array;
53
+ };
54
+ /**
55
+ * Parse the server response.
56
+ */
57
+ export declare function parseServerResponse(responseData: string): string;