@qidcloud/sdk 1.1.1 → 1.2.1

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,124 @@
1
+ import { QidCloud } from '../index';
2
+ import { QidFile, QidUploadResponse } from '../types';
3
+
4
+ export class VaultModule {
5
+ private sdk: QidCloud;
6
+
7
+ constructor(sdk: QidCloud) {
8
+ this.sdk = sdk;
9
+ }
10
+
11
+ /**
12
+ * Upload a file to the project's secure enclave storage
13
+ * @param file The file data (Buffer or Blob)
14
+ * @param fileName Name of the file
15
+ * @param metadata Optional E2EE metadata or custom tags
16
+ * @param userToken Session token for user-scoped storage
17
+ */
18
+ async upload(file: any, fileName: string, metadata: any = {}, userToken?: string): Promise<QidUploadResponse> {
19
+ const formData = new FormData();
20
+ formData.append('file', file, fileName);
21
+ formData.append('metadata', JSON.stringify(metadata));
22
+
23
+ const headers: any = {
24
+ 'Content-Type': 'multipart/form-data'
25
+ };
26
+ if (userToken) {
27
+ headers['Authorization'] = `Bearer ${userToken}`;
28
+ }
29
+
30
+ const resp = await this.sdk.api.post('/api/storage/upload', formData, { headers });
31
+ return resp.data;
32
+ }
33
+
34
+ /**
35
+ * List files in the project enclave
36
+ * @param userToken Session token for user-scoped storage
37
+ */
38
+ async list(userToken?: string): Promise<QidFile[]> {
39
+ const headers: any = {};
40
+ if (userToken) {
41
+ headers['Authorization'] = `Bearer ${userToken}`;
42
+ }
43
+
44
+ const resp = await this.sdk.api.get('/api/storage/list', { headers });
45
+ return resp.data;
46
+ }
47
+
48
+ /**
49
+ * Download a file from storage
50
+ * @param fileId Unique ID of the file
51
+ * @param userToken Session token for user-scoped storage
52
+ */
53
+ async download(fileId: string, userToken?: string): Promise<ArrayBuffer> {
54
+ const headers: any = {};
55
+ if (userToken) {
56
+ headers['Authorization'] = `Bearer ${userToken}`;
57
+ }
58
+
59
+ const resp = await this.sdk.api.get(`/api/storage/${fileId}`, {
60
+ headers,
61
+ responseType: 'arraybuffer'
62
+ });
63
+ return resp.data;
64
+ }
65
+
66
+ /**
67
+ * Delete a file from storage (Soft Delete)
68
+ * @param fileId Unique ID of the file
69
+ * @param userToken Session token for user-scoped storage
70
+ */
71
+ async delete(fileId: string, userToken?: string): Promise<{ success: boolean; message: string }> {
72
+ const headers: any = {};
73
+ if (userToken) {
74
+ headers['Authorization'] = `Bearer ${userToken}`;
75
+ }
76
+
77
+ const resp = await this.sdk.api.delete(`/api/storage/${fileId}`, { headers });
78
+ return resp.data;
79
+ }
80
+
81
+ /**
82
+ * List deleted files in the project enclave (Recycle Bin)
83
+ * @param userToken Session token for user-scoped storage
84
+ */
85
+ async listDeleted(userToken?: string): Promise<QidFile[]> {
86
+ const headers: any = {};
87
+ if (userToken) {
88
+ headers['Authorization'] = `Bearer ${userToken}`;
89
+ }
90
+
91
+ const resp = await this.sdk.api.get('/api/storage/deleted', { headers });
92
+ return resp.data;
93
+ }
94
+
95
+ /**
96
+ * Restore a deleted file from the recycle bin
97
+ * @param fileId Unique ID of the file
98
+ * @param userToken Session token for user-scoped storage
99
+ */
100
+ async restore(fileId: string, userToken?: string): Promise<{ success: boolean; message: string }> {
101
+ const headers: any = {};
102
+ if (userToken) {
103
+ headers['Authorization'] = `Bearer ${userToken}`;
104
+ }
105
+
106
+ const resp = await this.sdk.api.post(`/api/storage/restore/${fileId}`, {}, { headers });
107
+ return resp.data;
108
+ }
109
+
110
+ /**
111
+ * Permanently purge a deleted file
112
+ * @param fileId Unique ID of the file
113
+ * @param userToken Session token for user-scoped storage
114
+ */
115
+ async purge(fileId: string, userToken?: string): Promise<{ success: boolean; message: string }> {
116
+ const headers: any = {};
117
+ if (userToken) {
118
+ headers['Authorization'] = `Bearer ${userToken}`;
119
+ }
120
+
121
+ const resp = await this.sdk.api.delete(`/api/storage/purge/${fileId}`, { headers });
122
+ return resp.data;
123
+ }
124
+ }
package/src/types.ts ADDED
@@ -0,0 +1,52 @@
1
+ export interface QidConfig {
2
+ apiKey: string;
3
+ tenantId: string;
4
+ baseUrl?: string;
5
+ }
6
+
7
+ export interface QidUser {
8
+ userId: string;
9
+ regUserId: string;
10
+ username: string;
11
+ email?: string;
12
+ role: string;
13
+ }
14
+
15
+ export interface QidAuthSession {
16
+ sessionId: string;
17
+ qrData: string;
18
+ expiresAt: number;
19
+ }
20
+
21
+ export interface QidDbResponse<T = any> {
22
+ success: boolean;
23
+ data?: T;
24
+ error?: string;
25
+ count?: number;
26
+ }
27
+
28
+ export interface QidEdgeResponse {
29
+ success: boolean;
30
+ result: any;
31
+ computeTime: string;
32
+ logs?: string[];
33
+ }
34
+
35
+ export interface QidFile {
36
+ fileId: string;
37
+ originalName: string;
38
+ mimeType: string;
39
+ size: number;
40
+ createdAt: string;
41
+ clientMetadata?: any;
42
+ }
43
+
44
+ export interface QidUploadResponse {
45
+ success: boolean;
46
+ message: string;
47
+ file: {
48
+ id: string;
49
+ name: string;
50
+ url: string;
51
+ };
52
+ }
package/tsconfig.json CHANGED
@@ -1,20 +1,31 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES6",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "lib": [
7
- "DOM",
8
- "ES2017"
9
- ],
10
- "declaration": true,
11
- "outDir": "./dist",
12
- "strict": true,
13
- "esModuleInterop": true,
14
- "skipLibCheck": true,
15
- "forceConsistentCasingInFileNames": true
16
- },
17
- "include": [
18
- "src/**/*"
19
- ]
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "declaration": true,
7
+ "outDir": "./dist",
8
+ "strict": true,
9
+ "jsx": "react",
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "lib": [
14
+ "DOM",
15
+ "ESNext"
16
+ ],
17
+ "baseUrl": ".",
18
+ "paths": {
19
+ "*": [
20
+ "src/*"
21
+ ]
22
+ }
23
+ },
24
+ "include": [
25
+ "src/**/*"
26
+ ],
27
+ "exclude": [
28
+ "node_modules",
29
+ "dist"
30
+ ]
20
31
  }
@@ -1,31 +0,0 @@
1
- import { IStorage } from './storage';
2
- export interface QidConfig {
3
- baseUrl?: string;
4
- apiKey: string;
5
- storage?: IStorage;
6
- }
7
- export interface UserProfile {
8
- userId: string;
9
- username: string;
10
- role?: string;
11
- plan?: string;
12
- accountLimits?: {
13
- maxProjects: number;
14
- maxUsersTotal: number;
15
- };
16
- }
17
- export declare class QidCloud {
18
- private api;
19
- private storage;
20
- private config;
21
- constructor(config: QidConfig);
22
- hasIdentity(): Promise<boolean>;
23
- register(username: string, tenantId?: string): Promise<UserProfile>;
24
- /**
25
- * Login / Authenticate
26
- * Uses stored PQC keys to sign a challenge from the server
27
- */
28
- login(): Promise<string>;
29
- logout(): Promise<void>;
30
- getProfile(): Promise<UserProfile>;
31
- }
package/dist/QidCloud.js DELETED
@@ -1,142 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import axios from 'axios';
11
- import * as PQC from './crypto/pqc';
12
- import UnifiedStorage from './storage';
13
- import { generateUUID, toBase64, fromBase64 } from './utils';
14
- const DEFAULT_BACKEND_URL = 'https://qgate.onrender.com';
15
- export class QidCloud {
16
- constructor(config) {
17
- this.config = Object.assign(Object.assign({}, config), { baseUrl: config.baseUrl || DEFAULT_BACKEND_URL });
18
- this.storage = config.storage || UnifiedStorage;
19
- this.api = axios.create({
20
- baseURL: this.config.baseUrl,
21
- headers: {
22
- 'Content-Type': 'application/json',
23
- 'X-API-KEY': config.apiKey
24
- }
25
- });
26
- // Attach token interceptor
27
- this.api.interceptors.request.use((req) => __awaiter(this, void 0, void 0, function* () {
28
- const token = yield this.storage.getItem('qgate_token');
29
- if (token) {
30
- req.headers.Authorization = `Bearer ${token} `;
31
- }
32
- return req;
33
- }));
34
- }
35
- hasIdentity() {
36
- return __awaiter(this, void 0, void 0, function* () {
37
- const seed = yield this.storage.getItem('qgate_pqc_seed');
38
- return !!seed;
39
- });
40
- }
41
- register(username_1) {
42
- return __awaiter(this, arguments, void 0, function* (username, tenantId = 'default') {
43
- // 1. Generate Seed
44
- const seedHex = yield PQC.generateDilithiumSeed();
45
- // 2. Persist Locally
46
- yield this.storage.setItem('qgate_pqc_seed', seedHex);
47
- // 3. Derive Keys
48
- const keys = yield PQC.getKeysFromSeed(seedHex);
49
- const initResp = yield this.api.post('/api/register/initiate', { tenantId });
50
- const { regSessionId, regNonce } = initResp.data;
51
- // 4. Sign Nonce
52
- // Backend sends nonce as Base64
53
- const nonceBytes = fromBase64(regNonce);
54
- const signature = keys.sign(nonceBytes);
55
- const signatureBase64 = toBase64(signature);
56
- // 5. Complete Registration
57
- const completeResp = yield this.api.post('/api/register/complete', {
58
- regSessionId,
59
- did: generateUUID(), // Device ID
60
- username,
61
- attestation: {
62
- format: 'web-sdk',
63
- signature: signatureBase64,
64
- nonce: regNonce, // Echo back
65
- publicKey: toBase64(keys.publicKey)
66
- }
67
- });
68
- const { user, token } = completeResp.data;
69
- // 6. Store Session
70
- if (token) {
71
- yield this.storage.setItem('qgate_token', token);
72
- }
73
- if (user && user.userId) {
74
- yield this.storage.setItem('qgate_user_id', user.userId);
75
- return user;
76
- }
77
- return user || { userId: 'unknown', username };
78
- });
79
- }
80
- /**
81
- * Login / Authenticate
82
- * Uses stored PQC keys to sign a challenge from the server
83
- */
84
- login() {
85
- return __awaiter(this, void 0, void 0, function* () {
86
- if (!(yield this.hasIdentity())) {
87
- throw new Error('NO_IDENTITY: Device not registered. Call register() first.');
88
- }
89
- const seedHex = yield this.storage.getItem('qgate_pqc_seed');
90
- if (!seedHex) {
91
- throw new Error('NO_IDENTITY_SEED: Seed not found. Re-register.');
92
- }
93
- const keys = yield PQC.getKeysFromSeed(seedHex);
94
- // 1. Initiate Auth Challenge
95
- let userId = yield this.storage.getItem('qgate_user_id');
96
- if (!userId) {
97
- // Try to find user from profile if logged in? No, we are logging in.
98
- throw new Error('MISSING_USER_ID: Cannot look up user. Re-register.');
99
- }
100
- const initResp = yield this.api.post('/api/initiate', {
101
- regUserId: userId,
102
- clientHint: 'web-sdk'
103
- });
104
- const { sessionId, nonce } = initResp.data;
105
- // 2. Sign Challenge
106
- // Backend sends nonce as Base64
107
- const nonceBytes = fromBase64(nonce);
108
- const signature = keys.sign(nonceBytes);
109
- const signatureBase64 = toBase64(signature);
110
- // 3. Verify
111
- const verifyResp = yield this.api.post('/api/verify', {
112
- sessionId,
113
- signature: signatureBase64
114
- });
115
- const { token } = verifyResp.data;
116
- if (token) {
117
- yield this.storage.setItem('qgate_token', token);
118
- return token;
119
- }
120
- throw new Error('Authentication failed');
121
- });
122
- }
123
- logout() {
124
- return __awaiter(this, void 0, void 0, function* () {
125
- try {
126
- // Attempt to notify server
127
- yield this.api.post('/api/logout');
128
- }
129
- catch (e) {
130
- console.warn('Logout API call failed', e);
131
- }
132
- yield this.storage.removeItem('qgate_token');
133
- // Optional: Keep identity keys? Usually yes.
134
- });
135
- }
136
- getProfile() {
137
- return __awaiter(this, void 0, void 0, function* () {
138
- const resp = yield this.api.get('/api/me');
139
- return resp.data;
140
- });
141
- }
142
- }
@@ -1,12 +0,0 @@
1
- export declare function generateKyberKeyPair(): Promise<{
2
- publicKey: any;
3
- privateKey: any;
4
- }>;
5
- export declare function decapsulateSecret(privateKey: Uint8Array, cipherText: Uint8Array): Promise<any>;
6
- export declare function generateDilithiumSeed(): Promise<string>;
7
- export declare function getKeysFromSeed(seedHex: string): Promise<{
8
- publicKey: Uint8Array<ArrayBufferLike>;
9
- privateKey: Uint8Array<ArrayBufferLike>;
10
- sign: (msg: Uint8Array) => Uint8Array<ArrayBufferLike>;
11
- }>;
12
- export declare function signMessage(seedHex: string, message: Uint8Array | string): Promise<Uint8Array<ArrayBufferLike>>;
@@ -1,91 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- // PQC Crypto Utility for Q-Gate SDK
11
- import { DilithiumLevel, DilithiumKeyPair } from '@asanrom/dilithium';
12
- import { Kyber1024 } from 'crystals-kyber-js';
13
- import { hex2buf } from '../utils';
14
- export function generateKyberKeyPair() {
15
- return __awaiter(this, void 0, void 0, function* () {
16
- // Hardcoded sizes for Kyber1024
17
- const PK_SIZE = 1568;
18
- const SK_SIZE = 3168;
19
- // Assume Kyber1024 is a class we can instantiate or it has static methods.
20
- // Based on library patterns, if static props were missing, maybe it's an instance.
21
- const kyber = new Kyber1024();
22
- // Try async generation first
23
- try {
24
- // @ts-ignore
25
- if (kyber.generateKeyPair) {
26
- // @ts-ignore
27
- const [pk, sk] = yield kyber.generateKeyPair();
28
- return { publicKey: pk, privateKey: sk };
29
- }
30
- }
31
- catch (e) { }
32
- // Fallback to buffer passing
33
- const pk = new Uint8Array(PK_SIZE);
34
- const sk = new Uint8Array(SK_SIZE);
35
- // @ts-ignore
36
- kyber.keyPair(pk, sk);
37
- return {
38
- publicKey: pk,
39
- privateKey: sk
40
- };
41
- });
42
- }
43
- export function decapsulateSecret(privateKey, cipherText) {
44
- return __awaiter(this, void 0, void 0, function* () {
45
- const kyber = new Kyber1024();
46
- // @ts-ignore
47
- if (kyber.decap) {
48
- // @ts-ignore
49
- return yield kyber.decap(cipherText, privateKey);
50
- }
51
- // Fallback
52
- const SS_SIZE = 32;
53
- const sharedSecret = new Uint8Array(SS_SIZE);
54
- // @ts-ignore
55
- kyber.decaps(sharedSecret, cipherText, privateKey);
56
- return sharedSecret;
57
- });
58
- }
59
- export function generateDilithiumSeed() {
60
- return __awaiter(this, void 0, void 0, function* () {
61
- const seed = new Uint8Array(32);
62
- if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
63
- crypto.getRandomValues(seed);
64
- }
65
- else {
66
- for (let i = 0; i < 32; i++)
67
- seed[i] = Math.floor(Math.random() * 256);
68
- }
69
- return Array.prototype.map.call(seed, (x) => ('00' + x.toString(16)).slice(-2)).join('');
70
- });
71
- }
72
- export function getKeysFromSeed(seedHex) {
73
- return __awaiter(this, void 0, void 0, function* () {
74
- const level = DilithiumLevel.get(3);
75
- const seed = hex2buf(seedHex);
76
- const kp = DilithiumKeyPair.generate(level, seed);
77
- return {
78
- publicKey: kp.getPublicKey().getBytes(),
79
- privateKey: kp.getPrivateKey().getBytes(),
80
- // Helper to sign and return Uint8Array
81
- sign: (msg) => kp.sign(msg).getBytes()
82
- };
83
- });
84
- }
85
- export function signMessage(seedHex, message) {
86
- return __awaiter(this, void 0, void 0, function* () {
87
- const keys = yield getKeysFromSeed(seedHex);
88
- const msgBytes = typeof message === 'string' ? new TextEncoder().encode(message) : message;
89
- return keys.sign(msgBytes);
90
- });
91
- }
@@ -1,18 +0,0 @@
1
- export interface IStorage {
2
- getItem(key: string): Promise<string | null>;
3
- setItem(key: string, value: string): Promise<void>;
4
- removeItem(key: string): Promise<void>;
5
- }
6
- export declare class MemoryStorage implements IStorage {
7
- private storage;
8
- getItem(key: string): Promise<string | null>;
9
- setItem(key: string, value: string): Promise<void>;
10
- removeItem(key: string): Promise<void>;
11
- }
12
- export declare class LocalStorageAdapter implements IStorage {
13
- getItem(key: string): Promise<string | null>;
14
- setItem(key: string, value: string): Promise<void>;
15
- removeItem(key: string): Promise<void>;
16
- }
17
- declare const storage: MemoryStorage | LocalStorageAdapter;
18
- export default storage;
@@ -1,58 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- export class MemoryStorage {
11
- constructor() {
12
- this.storage = new Map();
13
- }
14
- getItem(key) {
15
- return __awaiter(this, void 0, void 0, function* () {
16
- return this.storage.get(key) || null;
17
- });
18
- }
19
- setItem(key, value) {
20
- return __awaiter(this, void 0, void 0, function* () {
21
- this.storage.set(key, value);
22
- });
23
- }
24
- removeItem(key) {
25
- return __awaiter(this, void 0, void 0, function* () {
26
- this.storage.delete(key);
27
- });
28
- }
29
- }
30
- export class LocalStorageAdapter {
31
- getItem(key) {
32
- return __awaiter(this, void 0, void 0, function* () {
33
- if (typeof window !== 'undefined' && window.localStorage) {
34
- return window.localStorage.getItem(key);
35
- }
36
- return null;
37
- });
38
- }
39
- setItem(key, value) {
40
- return __awaiter(this, void 0, void 0, function* () {
41
- if (typeof window !== 'undefined' && window.localStorage) {
42
- window.localStorage.setItem(key, value);
43
- }
44
- });
45
- }
46
- removeItem(key) {
47
- return __awaiter(this, void 0, void 0, function* () {
48
- if (typeof window !== 'undefined' && window.localStorage) {
49
- window.localStorage.removeItem(key);
50
- }
51
- });
52
- }
53
- }
54
- // Default export: Auto-detect
55
- const storage = typeof window !== 'undefined' && window.localStorage
56
- ? new LocalStorageAdapter()
57
- : new MemoryStorage();
58
- export default storage;
package/dist/utils.d.ts DELETED
@@ -1,5 +0,0 @@
1
- export declare function generateUUID(): string;
2
- export declare function buf2hex(buffer: Uint8Array): string;
3
- export declare function hex2buf(hex: string): Uint8Array;
4
- export declare function toBase64(bytes: Uint8Array): string;
5
- export declare function fromBase64(base64: string): Uint8Array;
package/dist/utils.js DELETED
@@ -1,46 +0,0 @@
1
- export function generateUUID() {
2
- if (typeof crypto !== 'undefined' && crypto.randomUUID) {
3
- return crypto.randomUUID();
4
- }
5
- // Fallback for environments without randomUUID
6
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
7
- var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
8
- return v.toString(16);
9
- });
10
- }
11
- export function buf2hex(buffer) {
12
- return Array.prototype.map.call(new Uint8Array(buffer), (x) => ('00' + x.toString(16)).slice(-2)).join('');
13
- }
14
- export function hex2buf(hex) {
15
- if (!hex)
16
- return new Uint8Array(0);
17
- const bytes = new Uint8Array(Math.ceil(hex.length / 2));
18
- for (let i = 0; i < bytes.length; i++)
19
- bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
20
- return bytes;
21
- }
22
- export function toBase64(bytes) {
23
- if (typeof Buffer !== 'undefined') {
24
- return Buffer.from(bytes).toString('base64');
25
- }
26
- // Browser fallback
27
- let binary = '';
28
- const len = bytes.byteLength;
29
- for (let i = 0; i < len; i++) {
30
- binary += String.fromCharCode(bytes[i]);
31
- }
32
- return window.btoa(binary);
33
- }
34
- export function fromBase64(base64) {
35
- if (typeof Buffer !== 'undefined') {
36
- return new Uint8Array(Buffer.from(base64, 'base64'));
37
- }
38
- // Browser fallback
39
- const binary_string = window.atob(base64);
40
- const len = binary_string.length;
41
- const bytes = new Uint8Array(len);
42
- for (let i = 0; i < len; i++) {
43
- bytes[i] = binary_string.charCodeAt(i);
44
- }
45
- return bytes;
46
- }