@stvor/sdk 2.0.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.
@@ -0,0 +1,65 @@
1
+ /**
2
+ * STVOR DX Facade - Type Definitions
3
+ */
4
+
5
+ /**
6
+ * AppToken from developer dashboard
7
+ * Replaces "API key" terminology for better DX
8
+ */
9
+ export type AppToken = string;
10
+
11
+ /**
12
+ * Configuration for SDK initialization
13
+ */
14
+ export interface StvorAppConfig {
15
+ /** AppToken from STVOR developer dashboard */
16
+ appToken: string;
17
+
18
+ /** Relay server URL (optional, defaults to stvor.io) */
19
+ relayUrl?: string;
20
+
21
+ /** Connection timeout in ms (optional, default 10000) */
22
+ timeout?: number;
23
+ }
24
+
25
+ /**
26
+ * User identifier in your application
27
+ * Can be email, username, or UUID
28
+ */
29
+ export type UserId = string;
30
+
31
+ /**
32
+ * Message content - text or binary data
33
+ */
34
+ export type MessageContent = string | Uint8Array;
35
+
36
+ /**
37
+ * Result of receiving a decrypted message
38
+ */
39
+ export interface DecryptedMessage {
40
+ /** Unique message identifier */
41
+ id: string;
42
+
43
+ /** Sender's user ID */
44
+ senderId: UserId;
45
+
46
+ /** Decrypted content */
47
+ content: MessageContent;
48
+
49
+ /** Timestamp when message was sent */
50
+ timestamp: Date;
51
+ }
52
+
53
+ /**
54
+ * Sealed payload for encrypting files/binary data
55
+ */
56
+ export interface SealedPayload {
57
+ /** Encrypted ciphertext */
58
+ ciphertext: Uint8Array;
59
+
60
+ /** Nonce used for encryption */
61
+ nonce: Uint8Array;
62
+
63
+ /** Recipient user ID this was sealed for */
64
+ recipientId: UserId;
65
+ }
package/index.ts ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * STVOR SDK - Main exports
3
+ */
4
+
5
+ // Legacy core API (for migration)
6
+ export * from './legacy';
7
+
8
+ // New DX Facade API
9
+ export * from './facade';
package/legacy.ts ADDED
@@ -0,0 +1,158 @@
1
+ /**
2
+ * STVOR SDK - Legacy Core API
3
+ * Kept for backwards compatibility
4
+ */
5
+
6
+ export interface StvorConfig {
7
+ apiKey: string;
8
+ serverUrl?: string;
9
+ }
10
+
11
+ export interface Peer {
12
+ id: string;
13
+ publicKey: any;
14
+ }
15
+
16
+ export interface EncryptedMessage {
17
+ ciphertext: string;
18
+ nonce: string;
19
+ from: string;
20
+ }
21
+
22
+ export class StvorClient {
23
+ private config: StvorConfig;
24
+ private myKeyPair: CryptoKeyPair | null = null;
25
+ private myId: string = '';
26
+ private peers: Map<string, CryptoKey> = new Map();
27
+
28
+ constructor(config: StvorConfig) {
29
+ this.config = {
30
+ serverUrl: 'http://localhost:3001',
31
+ ...config,
32
+ };
33
+ }
34
+
35
+ async ready(): Promise<void> {
36
+ if (!this.config.apiKey) {
37
+ throw new Error('API key is required');
38
+ }
39
+ this.myKeyPair = await crypto.subtle.generateKey(
40
+ { name: 'ECDH', namedCurve: 'P-256' },
41
+ true,
42
+ ['deriveKey', 'deriveBits']
43
+ );
44
+ this.myId = this.config.apiKey.substring(0, 8);
45
+ }
46
+
47
+ async createPeer(name: string): Promise<Peer> {
48
+ if (!this.myKeyPair) throw new Error('Call ready() first');
49
+
50
+ const publicKey = await crypto.subtle.exportKey('jwk', this.myKeyPair.publicKey);
51
+
52
+ const res = await fetch(`${this.config.serverUrl}/register`, {
53
+ method: 'POST',
54
+ headers: { 'Content-Type': 'application/json' },
55
+ body: JSON.stringify({ user_id: name, publicKey }),
56
+ });
57
+
58
+ if (!res.ok) {
59
+ const err = await res.json();
60
+ throw new Error(`Registration failed: ${JSON.stringify(err)}`);
61
+ }
62
+
63
+ return { id: name, publicKey };
64
+ }
65
+
66
+ async send({ to, message }: { to: string; message: string }): Promise<EncryptedMessage> {
67
+ if (!this.myKeyPair) throw new Error('Call ready() first');
68
+
69
+ let recipientKey = this.peers.get(to);
70
+ if (!recipientKey) {
71
+ const res = await fetch(`${this.config.serverUrl}/public-key/${to}`);
72
+ if (!res.ok) throw new Error(`Peer ${to} not found`);
73
+ const { publicKey } = await res.json();
74
+ recipientKey = await crypto.subtle.importKey(
75
+ 'jwk',
76
+ publicKey,
77
+ { name: 'ECDH', namedCurve: 'P-256' },
78
+ false,
79
+ []
80
+ );
81
+ this.peers.set(to, recipientKey);
82
+ }
83
+
84
+ const sharedKey = await crypto.subtle.deriveKey(
85
+ { name: 'ECDH', public: recipientKey },
86
+ this.myKeyPair.privateKey,
87
+ { name: 'AES-GCM', length: 256 },
88
+ false,
89
+ ['encrypt', 'decrypt']
90
+ );
91
+
92
+ const iv = crypto.getRandomValues(new Uint8Array(12));
93
+ const encoder = new TextEncoder();
94
+ const encrypted = await crypto.subtle.encrypt(
95
+ { name: 'AES-GCM', iv },
96
+ sharedKey,
97
+ encoder.encode(message)
98
+ );
99
+
100
+ const sendRes = await fetch(`${this.config.serverUrl}/message`, {
101
+ method: 'POST',
102
+ headers: { 'Content-Type': 'application/json' },
103
+ body: JSON.stringify({
104
+ from: this.myId,
105
+ to,
106
+ ciphertext: Buffer.from(encrypted).toString('base64'),
107
+ nonce: Buffer.from(iv).toString('base64'),
108
+ }),
109
+ });
110
+
111
+ if (!sendRes.ok) {
112
+ throw new Error('Failed to send message');
113
+ }
114
+
115
+ return {
116
+ ciphertext: Buffer.from(encrypted).toString('base64'),
117
+ nonce: Buffer.from(iv).toString('base64'),
118
+ from: this.myId
119
+ };
120
+ }
121
+
122
+ async receive(encrypted: EncryptedMessage): Promise<string> {
123
+ if (!this.myKeyPair) throw new Error('Call ready() first');
124
+
125
+ let senderKey = this.peers.get(encrypted.from);
126
+ if (!senderKey) {
127
+ const res = await fetch(`${this.config.serverUrl}/public-key/${encrypted.from}`);
128
+ if (!res.ok) throw new Error(`Sender ${encrypted.from} not found`);
129
+ const { publicKey } = await res.json();
130
+ senderKey = await crypto.subtle.importKey(
131
+ 'jwk',
132
+ publicKey,
133
+ { name: 'ECDH', namedCurve: 'P-256' },
134
+ false,
135
+ []
136
+ );
137
+ this.peers.set(encrypted.from, senderKey);
138
+ }
139
+
140
+ const sharedKey = await crypto.subtle.deriveKey(
141
+ { name: 'ECDH', public: senderKey },
142
+ this.myKeyPair.privateKey,
143
+ { name: 'AES-GCM', length: 256 },
144
+ false,
145
+ ['encrypt', 'decrypt']
146
+ );
147
+
148
+ const iv = Buffer.from(encrypted.nonce, 'base64');
149
+ const ciphertext = Buffer.from(encrypted.ciphertext, 'base64');
150
+ const decrypted = await crypto.subtle.decrypt(
151
+ { name: 'AES-GCM', iv },
152
+ sharedKey,
153
+ ciphertext
154
+ );
155
+
156
+ return new TextDecoder().decode(decrypted);
157
+ }
158
+ }
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@stvor/sdk",
3
+ "version": "2.0.0",
4
+ "description": "Stvor - is a security infrastructure for the quantum era.",
5
+ "type": "module",
6
+ "main": "index.ts",
7
+ "types": "index.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./index.ts",
11
+ "import": "./index.ts"
12
+ },
13
+ "./facade": {
14
+ "types": "./facade/index.ts",
15
+ "import": "./facade/index.ts"
16
+ }
17
+ },
18
+ "keywords": [
19
+ "e2ee",
20
+ "encryption",
21
+ "security",
22
+ "cryptography",
23
+ "end-to-end"
24
+ ],
25
+ "author": "Stvor",
26
+ "license": "MIT",
27
+ "engines": {
28
+ "node": ">=18.0.0"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/stvor/sdk/issues"
32
+ },
33
+ "homepage": "https://stvor.xyz"
34
+ }