@semiotic-labs/agentium-sdk 0.2.1 → 0.4.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.
- package/dist/index.d.ts +157 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +265 -6
- package/dist/index.js.map +1 -1
- package/dist/vc/index.d.ts +4 -0
- package/dist/vc/index.d.ts.map +1 -0
- package/dist/vc/index.js +6 -0
- package/dist/vc/index.js.map +1 -0
- package/dist/vc/storage.d.ts +26 -0
- package/dist/vc/storage.d.ts.map +1 -0
- package/dist/vc/storage.js +36 -0
- package/dist/vc/storage.js.map +1 -0
- package/dist/vc/test-helpers.d.ts +56 -0
- package/dist/vc/test-helpers.d.ts.map +1 -0
- package/dist/vc/test-helpers.js +101 -0
- package/dist/vc/test-helpers.js.map +1 -0
- package/dist/vc/types.d.ts +140 -0
- package/dist/vc/types.d.ts.map +1 -0
- package/dist/vc/types.js +10 -0
- package/dist/vc/types.js.map +1 -0
- package/dist/wasm.d.ts +48 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +73 -0
- package/dist/wasm.js.map +1 -0
- package/package.json +7 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { VcStorage, VerificationResult, DidDocument, JwtHeader } from './vc/index.js';
|
|
2
|
+
export * from './vc/index.js';
|
|
3
|
+
export { ensureWasmReady, initLogging, verifyJwt, generateKeypair, getPublicKey } from './wasm.js';
|
|
1
4
|
/**
|
|
2
5
|
* Options for configuring the AgentiumClient.
|
|
3
6
|
*/
|
|
@@ -8,6 +11,36 @@ export interface AgentiumClientOptions {
|
|
|
8
11
|
*/
|
|
9
12
|
baseURL?: string;
|
|
10
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Supported OAuth grant types for token exchange.
|
|
16
|
+
*/
|
|
17
|
+
export type GrantType = 'api_key' | 'refresh_token' | 'privy_id_token' | 'google_id_token' | 'external_google';
|
|
18
|
+
/**
|
|
19
|
+
* OAuth 2.0 token response from the backend.
|
|
20
|
+
*/
|
|
21
|
+
export interface OAuthTokenResponse {
|
|
22
|
+
/**
|
|
23
|
+
* JWT access token for authenticated API calls.
|
|
24
|
+
*/
|
|
25
|
+
access_token: string;
|
|
26
|
+
/**
|
|
27
|
+
* JWT refresh token for obtaining new access tokens.
|
|
28
|
+
*/
|
|
29
|
+
refresh_token: string;
|
|
30
|
+
/**
|
|
31
|
+
* Token type (always "Bearer").
|
|
32
|
+
*/
|
|
33
|
+
token_type: string;
|
|
34
|
+
/**
|
|
35
|
+
* Token expiration time in seconds.
|
|
36
|
+
*/
|
|
37
|
+
expires_in: number;
|
|
38
|
+
/**
|
|
39
|
+
* Space-separated scope string containing user info and DID.
|
|
40
|
+
* Format: "user did:pkh:eip155:1:0x... [new_user]"
|
|
41
|
+
*/
|
|
42
|
+
scope: string;
|
|
43
|
+
}
|
|
11
44
|
/**
|
|
12
45
|
* Represents the status of a user's badge.
|
|
13
46
|
*/
|
|
@@ -16,12 +49,9 @@ export interface Badge {
|
|
|
16
49
|
}
|
|
17
50
|
/**
|
|
18
51
|
* The response payload from a successful connect identity call.
|
|
52
|
+
* Extends OAuth token response with parsed identity information.
|
|
19
53
|
*/
|
|
20
54
|
export interface ConnectIdentityResponse {
|
|
21
|
-
/**
|
|
22
|
-
* The user's Privy ID.
|
|
23
|
-
*/
|
|
24
|
-
privy_user_id: string;
|
|
25
55
|
/**
|
|
26
56
|
* The user's Decentralized Identifier (DID).
|
|
27
57
|
*/
|
|
@@ -30,6 +60,34 @@ export interface ConnectIdentityResponse {
|
|
|
30
60
|
* Information about the user's badge status.
|
|
31
61
|
*/
|
|
32
62
|
badge: Badge;
|
|
63
|
+
/**
|
|
64
|
+
* Whether this is a newly created identity.
|
|
65
|
+
*/
|
|
66
|
+
isNew: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* JWT access token for authenticated API calls.
|
|
69
|
+
*/
|
|
70
|
+
accessToken: string;
|
|
71
|
+
/**
|
|
72
|
+
* JWT refresh token for obtaining new access tokens.
|
|
73
|
+
*/
|
|
74
|
+
refreshToken: string;
|
|
75
|
+
/**
|
|
76
|
+
* Token expiration time in seconds.
|
|
77
|
+
*/
|
|
78
|
+
expiresIn: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Options for connecting a Google identity.
|
|
82
|
+
*/
|
|
83
|
+
export interface ConnectGoogleIdentityOptions {
|
|
84
|
+
/**
|
|
85
|
+
* Skip audience validation for the Google token.
|
|
86
|
+
* Set to `true` when using tokens from external OAuth clients (e.g., zkLogin)
|
|
87
|
+
* that have a different Google Client ID than the backend.
|
|
88
|
+
* @default false
|
|
89
|
+
*/
|
|
90
|
+
skipAudienceValidation?: boolean;
|
|
33
91
|
}
|
|
34
92
|
/**
|
|
35
93
|
* Custom error class for API-related errors from the AgentiumClient.
|
|
@@ -44,7 +102,8 @@ export declare class AgentiumApiError extends Error {
|
|
|
44
102
|
export declare class AgentiumClient {
|
|
45
103
|
private readonly axiosInstance;
|
|
46
104
|
private readonly DEFAULT_BASE_URL;
|
|
47
|
-
private readonly
|
|
105
|
+
private readonly OAUTH_TOKEN_PATH;
|
|
106
|
+
private vcStorage;
|
|
48
107
|
/**
|
|
49
108
|
* Creates an instance of the AgentiumClient.
|
|
50
109
|
* @param options - Configuration options for the client.
|
|
@@ -53,12 +112,102 @@ export declare class AgentiumClient {
|
|
|
53
112
|
/**
|
|
54
113
|
* Connects a Google identity to an Agentium identity.
|
|
55
114
|
* @param googleToken - The JWT token obtained from Google Sign-In.
|
|
56
|
-
* @
|
|
115
|
+
* @param options - Optional configuration for the connection.
|
|
116
|
+
* @returns A promise that resolves with the connection response, containing the user's DID and tokens.
|
|
57
117
|
* @throws {AgentiumApiError} Will throw a custom API error if the call fails.
|
|
58
|
-
* - **400 (Bad Request):** The request was malformed
|
|
118
|
+
* - **400 (Bad Request):** The request was malformed or unsupported grant type.
|
|
59
119
|
* - **401 (Unauthorized):** The provided JWT token is invalid or expired.
|
|
60
120
|
* - **500 (Internal Server Error):** An unexpected error occurred on the server.
|
|
61
121
|
*/
|
|
62
|
-
connectGoogleIdentity(googleToken: string): Promise<ConnectIdentityResponse>;
|
|
122
|
+
connectGoogleIdentity(googleToken: string, options?: ConnectGoogleIdentityOptions): Promise<ConnectIdentityResponse>;
|
|
123
|
+
/**
|
|
124
|
+
* Exchanges an API key for JWT tokens (M2M authentication).
|
|
125
|
+
* @param apiKey - The API key to exchange.
|
|
126
|
+
* @returns A promise that resolves with the OAuth token response.
|
|
127
|
+
* @throws {AgentiumApiError} Will throw a custom API error if the call fails.
|
|
128
|
+
*/
|
|
129
|
+
exchangeApiKey(apiKey: string): Promise<OAuthTokenResponse>;
|
|
130
|
+
/**
|
|
131
|
+
* Refreshes an access token using a refresh token.
|
|
132
|
+
* @param refreshTokenValue - The refresh token to use.
|
|
133
|
+
* @returns A promise that resolves with the new OAuth token response.
|
|
134
|
+
* @throws {AgentiumApiError} Will throw a custom API error if the call fails.
|
|
135
|
+
*/
|
|
136
|
+
refreshToken(refreshTokenValue: string): Promise<OAuthTokenResponse>;
|
|
137
|
+
/**
|
|
138
|
+
* Exchanges a Privy ID token for JWT tokens.
|
|
139
|
+
* @param idToken - The Privy ID token to exchange.
|
|
140
|
+
* @returns A promise that resolves with the OAuth token response.
|
|
141
|
+
* @throws {AgentiumApiError} Will throw a custom API error if the call fails.
|
|
142
|
+
*/
|
|
143
|
+
exchangePrivyToken(idToken: string): Promise<OAuthTokenResponse>;
|
|
144
|
+
/**
|
|
145
|
+
* Configures VC storage for persisting membership credentials.
|
|
146
|
+
* Call this with `createBrowserStorage()` in browser environments.
|
|
147
|
+
*
|
|
148
|
+
* @param storage - Storage implementation to use
|
|
149
|
+
*/
|
|
150
|
+
setVcStorage(storage: VcStorage): void;
|
|
151
|
+
/**
|
|
152
|
+
* Retrieves the stored VC from storage (if any).
|
|
153
|
+
*
|
|
154
|
+
* @returns The stored JWT string, or null if none exists
|
|
155
|
+
*/
|
|
156
|
+
getStoredCredential(): string | null;
|
|
157
|
+
/**
|
|
158
|
+
* Fetches the issuer's DID document from /.well-known/did.json.
|
|
159
|
+
* The DID document contains the public key used to verify VCs.
|
|
160
|
+
*
|
|
161
|
+
* @returns The issuer's DID document
|
|
162
|
+
* @throws {AgentiumApiError} If the request fails
|
|
163
|
+
*/
|
|
164
|
+
fetchIssuerDidDocument(): Promise<DidDocument>;
|
|
165
|
+
/**
|
|
166
|
+
* Parses a JWT to extract the header (without verification).
|
|
167
|
+
*
|
|
168
|
+
* @param jwt - The JWT string
|
|
169
|
+
* @returns Parsed JWT header
|
|
170
|
+
* @throws {AgentiumApiError} If JWT format is invalid
|
|
171
|
+
*/
|
|
172
|
+
parseJwtHeader(jwt: string): JwtHeader;
|
|
173
|
+
/**
|
|
174
|
+
* Extracts the public key JWK from a DID document.
|
|
175
|
+
* If a key ID (kid) is provided, finds the matching verification method.
|
|
176
|
+
* Otherwise, uses the first verification method.
|
|
177
|
+
*
|
|
178
|
+
* @param didDocument - The DID document to extract from
|
|
179
|
+
* @param kid - Optional key ID to match (from JWT header)
|
|
180
|
+
* @returns The public key as a JSON string
|
|
181
|
+
* @throws {AgentiumApiError} If no matching public key is found
|
|
182
|
+
*/
|
|
183
|
+
extractPublicKeyJwk(didDocument: DidDocument, kid?: string): string;
|
|
184
|
+
/**
|
|
185
|
+
* Fetches a membership credential from the backend.
|
|
186
|
+
* Uses Privy auth token for authentication.
|
|
187
|
+
*
|
|
188
|
+
* @param privyToken - Privy auth token (NOT the accessToken from OAuth)
|
|
189
|
+
* @returns Raw JWT string
|
|
190
|
+
* @throws {AgentiumApiError} 401 if token invalid/expired, 403 if user banned
|
|
191
|
+
*/
|
|
192
|
+
fetchMembershipCredential(privyToken: string): Promise<string>;
|
|
193
|
+
/**
|
|
194
|
+
* Verifies a JWT-VC against the issuer's public key.
|
|
195
|
+
* Extracts the key ID from the JWT header, fetches the DID document,
|
|
196
|
+
* finds the matching public key, and uses WASM for Ed25519 verification.
|
|
197
|
+
*
|
|
198
|
+
* @param jwt - The JWT-VC to verify
|
|
199
|
+
* @returns Verification result with validity status, decoded claims, and structured error if invalid
|
|
200
|
+
*/
|
|
201
|
+
verifyCredential(jwt: string): Promise<VerificationResult>;
|
|
202
|
+
/**
|
|
203
|
+
* Full flow: fetch, verify, and store membership credential.
|
|
204
|
+
* Called immediately after identity connection ("Shadow Launch" mode).
|
|
205
|
+
*
|
|
206
|
+
* Per spec: errors are logged but user sees no change (silent failure).
|
|
207
|
+
*
|
|
208
|
+
* @param privyToken - Privy auth token
|
|
209
|
+
* @returns Verification result (always returns, never throws)
|
|
210
|
+
*/
|
|
211
|
+
connectAndStoreMembership(privyToken: string): Promise<VerificationResult>;
|
|
63
212
|
}
|
|
64
213
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
//
|
|
3
3
|
// SPDX-License-Identifier: MIT
|
|
4
4
|
import axios, { isAxiosError } from 'axios';
|
|
5
|
+
import { verifyJwt } from './wasm.js';
|
|
6
|
+
// Re-export VC module types and utilities
|
|
7
|
+
export * from './vc/index.js';
|
|
8
|
+
export { ensureWasmReady, initLogging, verifyJwt, generateKeypair, getPublicKey } from './wasm.js';
|
|
5
9
|
/**
|
|
6
10
|
* Custom error class for API-related errors from the AgentiumClient.
|
|
7
11
|
*/
|
|
@@ -13,13 +17,24 @@ export class AgentiumApiError extends Error {
|
|
|
13
17
|
this.statusCode = statusCode;
|
|
14
18
|
}
|
|
15
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Parses the OAuth scope string to extract the DID and new_user flag.
|
|
22
|
+
* Scope format: "user did:pkh:eip155:1:0x... [new_user]"
|
|
23
|
+
*/
|
|
24
|
+
function parseScopeForIdentity(scope) {
|
|
25
|
+
const parts = scope.split(/\s+/);
|
|
26
|
+
const did = parts.find((part) => part.startsWith('did:pkh:')) || '';
|
|
27
|
+
const isNew = parts.includes('new_user');
|
|
28
|
+
return { did, isNew };
|
|
29
|
+
}
|
|
16
30
|
/**
|
|
17
31
|
* A client for interacting with the Agentium API.
|
|
18
32
|
*/
|
|
19
33
|
export class AgentiumClient {
|
|
20
34
|
axiosInstance;
|
|
21
35
|
DEFAULT_BASE_URL = 'https://api.agentium.network';
|
|
22
|
-
|
|
36
|
+
OAUTH_TOKEN_PATH = '/oauth/token';
|
|
37
|
+
vcStorage = null;
|
|
23
38
|
/**
|
|
24
39
|
* Creates an instance of the AgentiumClient.
|
|
25
40
|
* @param options - Configuration options for the client.
|
|
@@ -33,26 +48,270 @@ export class AgentiumClient {
|
|
|
33
48
|
/**
|
|
34
49
|
* Connects a Google identity to an Agentium identity.
|
|
35
50
|
* @param googleToken - The JWT token obtained from Google Sign-In.
|
|
36
|
-
* @
|
|
51
|
+
* @param options - Optional configuration for the connection.
|
|
52
|
+
* @returns A promise that resolves with the connection response, containing the user's DID and tokens.
|
|
37
53
|
* @throws {AgentiumApiError} Will throw a custom API error if the call fails.
|
|
38
|
-
* - **400 (Bad Request):** The request was malformed
|
|
54
|
+
* - **400 (Bad Request):** The request was malformed or unsupported grant type.
|
|
39
55
|
* - **401 (Unauthorized):** The provided JWT token is invalid or expired.
|
|
40
56
|
* - **500 (Internal Server Error):** An unexpected error occurred on the server.
|
|
41
57
|
*/
|
|
42
|
-
async connectGoogleIdentity(googleToken) {
|
|
58
|
+
async connectGoogleIdentity(googleToken, options = {}) {
|
|
59
|
+
const grantType = options.skipAudienceValidation
|
|
60
|
+
? 'external_google'
|
|
61
|
+
: 'google_id_token';
|
|
43
62
|
try {
|
|
44
|
-
const response = await this.axiosInstance.post(this.
|
|
63
|
+
const response = await this.axiosInstance.post(this.OAUTH_TOKEN_PATH, {
|
|
64
|
+
grant_type: grantType,
|
|
45
65
|
id_token: googleToken,
|
|
46
66
|
});
|
|
67
|
+
const { did, isNew } = parseScopeForIdentity(response.data.scope);
|
|
68
|
+
return {
|
|
69
|
+
did,
|
|
70
|
+
badge: { status: isNew ? 'Active' : 'Existing' },
|
|
71
|
+
isNew,
|
|
72
|
+
accessToken: response.data.access_token,
|
|
73
|
+
refreshToken: response.data.refresh_token,
|
|
74
|
+
expiresIn: response.data.expires_in,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (isAxiosError(error)) {
|
|
79
|
+
throw new AgentiumApiError(error.message, error.response?.status);
|
|
80
|
+
}
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Exchanges an API key for JWT tokens (M2M authentication).
|
|
86
|
+
* @param apiKey - The API key to exchange.
|
|
87
|
+
* @returns A promise that resolves with the OAuth token response.
|
|
88
|
+
* @throws {AgentiumApiError} Will throw a custom API error if the call fails.
|
|
89
|
+
*/
|
|
90
|
+
async exchangeApiKey(apiKey) {
|
|
91
|
+
try {
|
|
92
|
+
const response = await this.axiosInstance.post(this.OAUTH_TOKEN_PATH, {
|
|
93
|
+
grant_type: 'api_key',
|
|
94
|
+
api_key: apiKey,
|
|
95
|
+
});
|
|
47
96
|
return response.data;
|
|
48
97
|
}
|
|
49
98
|
catch (error) {
|
|
50
99
|
if (isAxiosError(error)) {
|
|
51
100
|
throw new AgentiumApiError(error.message, error.response?.status);
|
|
52
101
|
}
|
|
53
|
-
// Re-throw other unexpected errors
|
|
54
102
|
throw error;
|
|
55
103
|
}
|
|
56
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Refreshes an access token using a refresh token.
|
|
107
|
+
* @param refreshTokenValue - The refresh token to use.
|
|
108
|
+
* @returns A promise that resolves with the new OAuth token response.
|
|
109
|
+
* @throws {AgentiumApiError} Will throw a custom API error if the call fails.
|
|
110
|
+
*/
|
|
111
|
+
async refreshToken(refreshTokenValue) {
|
|
112
|
+
try {
|
|
113
|
+
const response = await this.axiosInstance.post(this.OAUTH_TOKEN_PATH, {
|
|
114
|
+
grant_type: 'refresh_token',
|
|
115
|
+
refresh_token: refreshTokenValue,
|
|
116
|
+
});
|
|
117
|
+
return response.data;
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
if (isAxiosError(error)) {
|
|
121
|
+
throw new AgentiumApiError(error.message, error.response?.status);
|
|
122
|
+
}
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Exchanges a Privy ID token for JWT tokens.
|
|
128
|
+
* @param idToken - The Privy ID token to exchange.
|
|
129
|
+
* @returns A promise that resolves with the OAuth token response.
|
|
130
|
+
* @throws {AgentiumApiError} Will throw a custom API error if the call fails.
|
|
131
|
+
*/
|
|
132
|
+
async exchangePrivyToken(idToken) {
|
|
133
|
+
try {
|
|
134
|
+
const response = await this.axiosInstance.post(this.OAUTH_TOKEN_PATH, {
|
|
135
|
+
grant_type: 'privy_id_token',
|
|
136
|
+
id_token: idToken,
|
|
137
|
+
});
|
|
138
|
+
return response.data;
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
if (isAxiosError(error)) {
|
|
142
|
+
throw new AgentiumApiError(error.message, error.response?.status);
|
|
143
|
+
}
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
148
|
+
// Verifiable Credentials (VC) Methods
|
|
149
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
150
|
+
/**
|
|
151
|
+
* Configures VC storage for persisting membership credentials.
|
|
152
|
+
* Call this with `createBrowserStorage()` in browser environments.
|
|
153
|
+
*
|
|
154
|
+
* @param storage - Storage implementation to use
|
|
155
|
+
*/
|
|
156
|
+
setVcStorage(storage) {
|
|
157
|
+
this.vcStorage = storage;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Retrieves the stored VC from storage (if any).
|
|
161
|
+
*
|
|
162
|
+
* @returns The stored JWT string, or null if none exists
|
|
163
|
+
*/
|
|
164
|
+
getStoredCredential() {
|
|
165
|
+
return this.vcStorage?.get() ?? null;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Fetches the issuer's DID document from /.well-known/did.json.
|
|
169
|
+
* The DID document contains the public key used to verify VCs.
|
|
170
|
+
*
|
|
171
|
+
* @returns The issuer's DID document
|
|
172
|
+
* @throws {AgentiumApiError} If the request fails
|
|
173
|
+
*/
|
|
174
|
+
async fetchIssuerDidDocument() {
|
|
175
|
+
try {
|
|
176
|
+
const response = await this.axiosInstance.get('/.well-known/did.json');
|
|
177
|
+
return response.data;
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
if (isAxiosError(error)) {
|
|
181
|
+
throw new AgentiumApiError(error.message, error.response?.status);
|
|
182
|
+
}
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Parses a JWT to extract the header (without verification).
|
|
188
|
+
*
|
|
189
|
+
* @param jwt - The JWT string
|
|
190
|
+
* @returns Parsed JWT header
|
|
191
|
+
* @throws {AgentiumApiError} If JWT format is invalid
|
|
192
|
+
*/
|
|
193
|
+
parseJwtHeader(jwt) {
|
|
194
|
+
const parts = jwt.split('.');
|
|
195
|
+
if (parts.length !== 3) {
|
|
196
|
+
throw new AgentiumApiError('Invalid JWT format: expected 3 parts');
|
|
197
|
+
}
|
|
198
|
+
const headerPart = parts[0];
|
|
199
|
+
if (!headerPart) {
|
|
200
|
+
throw new AgentiumApiError('Invalid JWT format: missing header');
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
const headerJson = atob(headerPart.replace(/-/g, '+').replace(/_/g, '/'));
|
|
204
|
+
return JSON.parse(headerJson);
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
throw new AgentiumApiError('Invalid JWT header encoding');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Extracts the public key JWK from a DID document.
|
|
212
|
+
* If a key ID (kid) is provided, finds the matching verification method.
|
|
213
|
+
* Otherwise, uses the first verification method.
|
|
214
|
+
*
|
|
215
|
+
* @param didDocument - The DID document to extract from
|
|
216
|
+
* @param kid - Optional key ID to match (from JWT header)
|
|
217
|
+
* @returns The public key as a JSON string
|
|
218
|
+
* @throws {AgentiumApiError} If no matching public key is found
|
|
219
|
+
*/
|
|
220
|
+
extractPublicKeyJwk(didDocument, kid) {
|
|
221
|
+
const methods = didDocument.verificationMethod;
|
|
222
|
+
if (!methods || methods.length === 0) {
|
|
223
|
+
throw new AgentiumApiError('No verification methods found in DID document');
|
|
224
|
+
}
|
|
225
|
+
let verificationMethod = methods[0];
|
|
226
|
+
// If kid is provided, find the matching verification method
|
|
227
|
+
if (kid) {
|
|
228
|
+
const matched = methods.find((m) => m.id === kid);
|
|
229
|
+
if (matched) {
|
|
230
|
+
verificationMethod = matched;
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
// kid might be just the fragment (e.g., "key-1"), try matching suffix
|
|
234
|
+
const matchedByFragment = methods.find((m) => m.id.endsWith(`#${kid}`) || m.id === kid);
|
|
235
|
+
if (matchedByFragment) {
|
|
236
|
+
verificationMethod = matchedByFragment;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (!verificationMethod?.publicKeyJwk) {
|
|
241
|
+
throw new AgentiumApiError(kid ? `No public key found for kid: ${kid}` : 'No public key found in DID document');
|
|
242
|
+
}
|
|
243
|
+
return JSON.stringify(verificationMethod.publicKeyJwk);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Fetches a membership credential from the backend.
|
|
247
|
+
* Uses Privy auth token for authentication.
|
|
248
|
+
*
|
|
249
|
+
* @param privyToken - Privy auth token (NOT the accessToken from OAuth)
|
|
250
|
+
* @returns Raw JWT string
|
|
251
|
+
* @throws {AgentiumApiError} 401 if token invalid/expired, 403 if user banned
|
|
252
|
+
*/
|
|
253
|
+
async fetchMembershipCredential(privyToken) {
|
|
254
|
+
try {
|
|
255
|
+
const response = await this.axiosInstance.post('/v1/credentials/membership', {}, { headers: { Authorization: `Bearer ${privyToken}` } });
|
|
256
|
+
return response.data.vc;
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
if (isAxiosError(error)) {
|
|
260
|
+
throw new AgentiumApiError(error.message, error.response?.status);
|
|
261
|
+
}
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Verifies a JWT-VC against the issuer's public key.
|
|
267
|
+
* Extracts the key ID from the JWT header, fetches the DID document,
|
|
268
|
+
* finds the matching public key, and uses WASM for Ed25519 verification.
|
|
269
|
+
*
|
|
270
|
+
* @param jwt - The JWT-VC to verify
|
|
271
|
+
* @returns Verification result with validity status, decoded claims, and structured error if invalid
|
|
272
|
+
*/
|
|
273
|
+
async verifyCredential(jwt) {
|
|
274
|
+
// Extract kid from JWT header to find the correct key
|
|
275
|
+
const header = this.parseJwtHeader(jwt);
|
|
276
|
+
const didDocument = await this.fetchIssuerDidDocument();
|
|
277
|
+
const publicKeyJwk = this.extractPublicKeyJwk(didDocument, header.kid);
|
|
278
|
+
return verifyJwt(jwt, publicKeyJwk);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Full flow: fetch, verify, and store membership credential.
|
|
282
|
+
* Called immediately after identity connection ("Shadow Launch" mode).
|
|
283
|
+
*
|
|
284
|
+
* Per spec: errors are logged but user sees no change (silent failure).
|
|
285
|
+
*
|
|
286
|
+
* @param privyToken - Privy auth token
|
|
287
|
+
* @returns Verification result (always returns, never throws)
|
|
288
|
+
*/
|
|
289
|
+
async connectAndStoreMembership(privyToken) {
|
|
290
|
+
try {
|
|
291
|
+
const jwt = await this.fetchMembershipCredential(privyToken);
|
|
292
|
+
const result = await this.verifyCredential(jwt);
|
|
293
|
+
if (result.valid && this.vcStorage) {
|
|
294
|
+
this.vcStorage.set(jwt);
|
|
295
|
+
// TODO: Log analytics: "VC Success"
|
|
296
|
+
}
|
|
297
|
+
else if (!result.valid) {
|
|
298
|
+
// TODO: Log analytics: "VC Verification Failed"
|
|
299
|
+
console.warn('[Agentium] VC verification failed:', result.error);
|
|
300
|
+
}
|
|
301
|
+
return result;
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
// Silent failure per spec - log but don't throw
|
|
305
|
+
// Note: verifyJwt no longer throws; this only catches fetch/DID errors
|
|
306
|
+
console.warn('[Agentium] VC fetch/verify error:', error);
|
|
307
|
+
return {
|
|
308
|
+
valid: false,
|
|
309
|
+
error: {
|
|
310
|
+
code: 'VERIFICATION_FAILED',
|
|
311
|
+
message: error instanceof Error ? error.message : String(error),
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
}
|
|
57
316
|
}
|
|
58
317
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,+BAA+B;AAE/B,OAAO,KAAK,EAAE,EAAE,YAAY,EAAsB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { CredentialSubject, VerifiableCredential, VcJwtClaims, VerificationResult, VerificationError, DidDocument, VerificationMethod, JsonWebKey, JwtHeader, KeyPair, VcErrorCode, WasmVcError, } from './types.js';
|
|
2
|
+
export { isWasmVcError } from './types.js';
|
|
3
|
+
export { type VcStorage, createBrowserStorage, createMemoryStorage } from './storage.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vc/index.ts"],"names":[],"mappings":"AAIA,YAAY,EACV,iBAAiB,EACjB,oBAAoB,EACpB,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,kBAAkB,EAClB,UAAU,EACV,SAAS,EACT,OAAO,EACP,WAAW,EACX,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,KAAK,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/vc/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vc/index.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,+BAA+B;AAgB/B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAkB,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage interface for persisting membership VCs.
|
|
3
|
+
*/
|
|
4
|
+
export interface VcStorage {
|
|
5
|
+
/** Retrieve the stored VC JWT, or null if none exists */
|
|
6
|
+
get(): string | null;
|
|
7
|
+
/** Store a VC JWT */
|
|
8
|
+
set(jwt: string): void;
|
|
9
|
+
/** Remove the stored VC */
|
|
10
|
+
clear(): void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a browser storage implementation using LocalStorage.
|
|
14
|
+
* Use this in browser environments.
|
|
15
|
+
*
|
|
16
|
+
* @returns VcStorage implementation backed by LocalStorage
|
|
17
|
+
*/
|
|
18
|
+
export declare function createBrowserStorage(): VcStorage;
|
|
19
|
+
/**
|
|
20
|
+
* Creates an in-memory storage implementation.
|
|
21
|
+
* Use this for Node.js environments or testing.
|
|
22
|
+
*
|
|
23
|
+
* @returns VcStorage implementation backed by memory
|
|
24
|
+
*/
|
|
25
|
+
export declare function createMemoryStorage(): VcStorage;
|
|
26
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/vc/storage.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,yDAAyD;IACzD,GAAG,IAAI,MAAM,GAAG,IAAI,CAAC;IACrB,qBAAqB;IACrB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,2BAA2B;IAC3B,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,SAAS,CAMhD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,SAAS,CAW/C"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 Semiotic AI, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: MIT
|
|
4
|
+
const STORAGE_KEY = 'agentium:membership_vc';
|
|
5
|
+
/**
|
|
6
|
+
* Creates a browser storage implementation using LocalStorage.
|
|
7
|
+
* Use this in browser environments.
|
|
8
|
+
*
|
|
9
|
+
* @returns VcStorage implementation backed by LocalStorage
|
|
10
|
+
*/
|
|
11
|
+
export function createBrowserStorage() {
|
|
12
|
+
return {
|
|
13
|
+
get: () => localStorage.getItem(STORAGE_KEY),
|
|
14
|
+
set: (jwt) => localStorage.setItem(STORAGE_KEY, jwt),
|
|
15
|
+
clear: () => localStorage.removeItem(STORAGE_KEY),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates an in-memory storage implementation.
|
|
20
|
+
* Use this for Node.js environments or testing.
|
|
21
|
+
*
|
|
22
|
+
* @returns VcStorage implementation backed by memory
|
|
23
|
+
*/
|
|
24
|
+
export function createMemoryStorage() {
|
|
25
|
+
let stored = null;
|
|
26
|
+
return {
|
|
27
|
+
get: () => stored,
|
|
28
|
+
set: (jwt) => {
|
|
29
|
+
stored = jwt;
|
|
30
|
+
},
|
|
31
|
+
clear: () => {
|
|
32
|
+
stored = null;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/vc/storage.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,+BAA+B;AAE/B,MAAM,WAAW,GAAG,wBAAwB,CAAC;AAc7C;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO;QACL,GAAG,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC;QAC5C,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC;QACpD,KAAK,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC;KAClD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB;IACjC,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,OAAO;QACL,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM;QACjB,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,GAAG,GAAG,CAAC;QACf,CAAC;QACD,KAAK,EAAE,GAAG,EAAE;YACV,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { DidDocument } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Test keypair with JWK strings (matching WASM output format).
|
|
4
|
+
*/
|
|
5
|
+
export interface TestKeyPair {
|
|
6
|
+
privateJwk: string;
|
|
7
|
+
publicJwk: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Options for issuing a test JWT-VC.
|
|
11
|
+
*/
|
|
12
|
+
export interface IssueJwtOptions {
|
|
13
|
+
/** Issuer DID (e.g., did:web:api.agentium.network) */
|
|
14
|
+
issuerDid: string;
|
|
15
|
+
/** Subject DID (e.g., did:pkh:eip155:1:0x...) */
|
|
16
|
+
subjectDid: string;
|
|
17
|
+
/** Enrollment time (ISO 8601 format) */
|
|
18
|
+
enrollmentTime?: string;
|
|
19
|
+
privateJwk: string;
|
|
20
|
+
/** Hours until expiration (default: 24). Use negative for expired JWTs. */
|
|
21
|
+
expiresInHours?: number;
|
|
22
|
+
/** Key ID to include in JWT header (for DID resolution) */
|
|
23
|
+
kid?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate an Ed25519 keypair for testing.
|
|
27
|
+
* Returns JWK strings matching the WASM generate_keypair() output format.
|
|
28
|
+
*/
|
|
29
|
+
export declare function generateTestKeypair(): Promise<TestKeyPair>;
|
|
30
|
+
/**
|
|
31
|
+
* Issue a W3C-compliant JWT-VC matching backend SSI structure.
|
|
32
|
+
*/
|
|
33
|
+
export declare function issueTestJwt(options: IssueJwtOptions): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Generate a DID document for testing.
|
|
36
|
+
* Uses camelCase field names matching W3C spec and backend.
|
|
37
|
+
*/
|
|
38
|
+
export declare function generateTestDidDocument(did: string, publicJwk: string, keyId?: string): DidDocument;
|
|
39
|
+
/**
|
|
40
|
+
* Create a complete test fixture with keypair, DID document, and JWT.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createTestFixture(options?: {
|
|
43
|
+
did?: string;
|
|
44
|
+
subjectDid?: string;
|
|
45
|
+
enrollmentTime?: string;
|
|
46
|
+
keyId?: string;
|
|
47
|
+
expiresInHours?: number;
|
|
48
|
+
}): Promise<{
|
|
49
|
+
keypair: TestKeyPair;
|
|
50
|
+
didDocument: DidDocument;
|
|
51
|
+
jwt: string;
|
|
52
|
+
did: string;
|
|
53
|
+
subjectDid: string;
|
|
54
|
+
enrollmentTime: string;
|
|
55
|
+
}>;
|
|
56
|
+
//# sourceMappingURL=test-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../../src/vc/test-helpers.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAuD,MAAM,YAAY,CAAC;AAEnG;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,WAAW,CAAC,CAahE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAwC5E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,MAAgB,GACtB,WAAW,CAgBb;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,CAAC,EAAE;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;;;;;;;GA6BA"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 Semiotic AI, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: MIT
|
|
4
|
+
/**
|
|
5
|
+
* Test helpers for VC integration tests.
|
|
6
|
+
* Uses jose library for Ed25519 JWT signing.
|
|
7
|
+
* Generates W3C-compliant VCs matching backend SSI implementation.
|
|
8
|
+
*/
|
|
9
|
+
import * as jose from 'jose';
|
|
10
|
+
/**
|
|
11
|
+
* Generate an Ed25519 keypair for testing.
|
|
12
|
+
* Returns JWK strings matching the WASM generate_keypair() output format.
|
|
13
|
+
*/
|
|
14
|
+
export async function generateTestKeypair() {
|
|
15
|
+
const { privateKey, publicKey } = await jose.generateKeyPair('EdDSA', {
|
|
16
|
+
crv: 'Ed25519',
|
|
17
|
+
extractable: true,
|
|
18
|
+
});
|
|
19
|
+
const privateJwk = await jose.exportJWK(privateKey);
|
|
20
|
+
const publicJwk = await jose.exportJWK(publicKey);
|
|
21
|
+
return {
|
|
22
|
+
privateJwk: JSON.stringify(privateJwk),
|
|
23
|
+
publicJwk: JSON.stringify(publicJwk),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Issue a W3C-compliant JWT-VC matching backend SSI structure.
|
|
28
|
+
*/
|
|
29
|
+
export async function issueTestJwt(options) {
|
|
30
|
+
const { issuerDid, subjectDid, enrollmentTime = new Date().toISOString(), privateJwk, expiresInHours = 24, kid, } = options;
|
|
31
|
+
const jwk = JSON.parse(privateJwk);
|
|
32
|
+
const privateKey = await jose.importJWK(jwk, 'EdDSA');
|
|
33
|
+
const now = Math.floor(Date.now() / 1000);
|
|
34
|
+
const exp = now + expiresInHours * 3600;
|
|
35
|
+
// Build W3C VC structure matching backend SSI output
|
|
36
|
+
const credentialSubject = {
|
|
37
|
+
id: subjectDid,
|
|
38
|
+
enrollmentTime: enrollmentTime,
|
|
39
|
+
};
|
|
40
|
+
const vc = {
|
|
41
|
+
'@context': ['https://www.w3.org/2018/credentials/v1'],
|
|
42
|
+
type: ['VerifiableCredential'],
|
|
43
|
+
issuer: { id: issuerDid },
|
|
44
|
+
issuanceDate: enrollmentTime,
|
|
45
|
+
credentialSubject: credentialSubject,
|
|
46
|
+
};
|
|
47
|
+
// JWT claims with nested VC (W3C JWT-VC format)
|
|
48
|
+
const builder = new jose.SignJWT({
|
|
49
|
+
vc,
|
|
50
|
+
})
|
|
51
|
+
.setProtectedHeader({ alg: 'EdDSA', typ: 'JWT', ...(kid ? { kid } : {}) })
|
|
52
|
+
.setSubject(subjectDid)
|
|
53
|
+
.setIssuedAt(now)
|
|
54
|
+
.setExpirationTime(exp);
|
|
55
|
+
return builder.sign(privateKey);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Generate a DID document for testing.
|
|
59
|
+
* Uses camelCase field names matching W3C spec and backend.
|
|
60
|
+
*/
|
|
61
|
+
export function generateTestDidDocument(did, publicJwk, keyId = 'key-1') {
|
|
62
|
+
const publicKey = JSON.parse(publicJwk);
|
|
63
|
+
const fullKeyId = `${did}#${keyId}`;
|
|
64
|
+
return {
|
|
65
|
+
id: did,
|
|
66
|
+
verificationMethod: [
|
|
67
|
+
{
|
|
68
|
+
id: fullKeyId,
|
|
69
|
+
type: 'JsonWebKey2020',
|
|
70
|
+
controller: did,
|
|
71
|
+
publicKeyJwk: publicKey,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
authentication: [fullKeyId],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Create a complete test fixture with keypair, DID document, and JWT.
|
|
79
|
+
*/
|
|
80
|
+
export async function createTestFixture(options) {
|
|
81
|
+
const { did = 'did:web:test.example', subjectDid = 'did:pkh:eip155:1:0x1234567890abcdef', enrollmentTime = new Date().toISOString(), keyId = 'key-1', expiresInHours = 24, } = options ?? {};
|
|
82
|
+
const keypair = await generateTestKeypair();
|
|
83
|
+
const didDocument = generateTestDidDocument(did, keypair.publicJwk, keyId);
|
|
84
|
+
const jwt = await issueTestJwt({
|
|
85
|
+
issuerDid: did,
|
|
86
|
+
subjectDid,
|
|
87
|
+
enrollmentTime,
|
|
88
|
+
privateJwk: keypair.privateJwk,
|
|
89
|
+
expiresInHours,
|
|
90
|
+
kid: `${did}#${keyId}`,
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
keypair,
|
|
94
|
+
didDocument,
|
|
95
|
+
jwt,
|
|
96
|
+
did,
|
|
97
|
+
subjectDid,
|
|
98
|
+
enrollmentTime,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=test-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../../src/vc/test-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential subject containing user identity and enrollment info.
|
|
3
|
+
* Matches backend's MembershipCredentialSubject.
|
|
4
|
+
*/
|
|
5
|
+
export interface CredentialSubject {
|
|
6
|
+
/** User's DID (did:pkh) */
|
|
7
|
+
id: string;
|
|
8
|
+
/** Enrollment timestamp (ISO 8601 format) */
|
|
9
|
+
enrollmentTime: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* W3C Verifiable Credential structure.
|
|
13
|
+
* Backend issues VCs using SSI library with this structure.
|
|
14
|
+
*/
|
|
15
|
+
export interface VerifiableCredential {
|
|
16
|
+
/** JSON-LD context */
|
|
17
|
+
'@context': string[];
|
|
18
|
+
/** Credential types */
|
|
19
|
+
type: string[];
|
|
20
|
+
/** Issuer DID (as object with id) */
|
|
21
|
+
issuer: {
|
|
22
|
+
id: string;
|
|
23
|
+
};
|
|
24
|
+
/** Issuance date (ISO 8601 format) */
|
|
25
|
+
issuanceDate: string;
|
|
26
|
+
/** Credential subject with user info */
|
|
27
|
+
credentialSubject: CredentialSubject;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* JWT claims structure for W3C VC (as issued by backend).
|
|
31
|
+
* The VC is nested under the 'vc' claim per JWT-VC spec.
|
|
32
|
+
* This is returned directly from verification - matches backend exactly.
|
|
33
|
+
*/
|
|
34
|
+
export interface VcJwtClaims {
|
|
35
|
+
/** The Verifiable Credential */
|
|
36
|
+
vc: VerifiableCredential;
|
|
37
|
+
/** Subject (user DID) */
|
|
38
|
+
sub: string;
|
|
39
|
+
/** Expiration time (Unix timestamp) */
|
|
40
|
+
exp: number;
|
|
41
|
+
/** Issued at time (Unix timestamp, optional) */
|
|
42
|
+
iat?: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Structured error returned in VerificationResult when verification fails.
|
|
46
|
+
*/
|
|
47
|
+
export interface VerificationError {
|
|
48
|
+
/** Stable error code */
|
|
49
|
+
code: VcErrorCode;
|
|
50
|
+
/** Human-readable error message */
|
|
51
|
+
message: string;
|
|
52
|
+
/** Optional metadata (e.g., expiredAt for JWT_EXPIRED) */
|
|
53
|
+
data?: {
|
|
54
|
+
expiredAt?: string;
|
|
55
|
+
} | undefined;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Result of JWT-VC verification from WASM module.
|
|
59
|
+
*/
|
|
60
|
+
export interface VerificationResult {
|
|
61
|
+
/** Whether the signature is valid and claims passed validation */
|
|
62
|
+
valid: boolean;
|
|
63
|
+
/** JWT claims if verification succeeded (matches backend structure exactly) */
|
|
64
|
+
claims?: VcJwtClaims | undefined;
|
|
65
|
+
/** Structured error if verification failed */
|
|
66
|
+
error?: VerificationError | undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* W3C DID Document structure (subset of fields we need).
|
|
70
|
+
*/
|
|
71
|
+
export interface DidDocument {
|
|
72
|
+
/** DID identifier (e.g., "did:web:api.agentium.network") */
|
|
73
|
+
id: string;
|
|
74
|
+
/** Verification methods containing public keys (camelCase per W3C spec) */
|
|
75
|
+
verificationMethod: VerificationMethod[];
|
|
76
|
+
/** Authentication method references */
|
|
77
|
+
authentication?: string[];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Verification method within a DID Document.
|
|
81
|
+
*/
|
|
82
|
+
export interface VerificationMethod {
|
|
83
|
+
/** Full key ID (e.g., "did:web:api.agentium.network#key-1") */
|
|
84
|
+
id: string;
|
|
85
|
+
/** Key type (e.g., "JsonWebKey2020") */
|
|
86
|
+
type: string;
|
|
87
|
+
/** Controller DID */
|
|
88
|
+
controller: string;
|
|
89
|
+
/** Public key in JWK format */
|
|
90
|
+
publicKeyJwk: JsonWebKey;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* JWT header structure for extracting key ID.
|
|
94
|
+
*/
|
|
95
|
+
export interface JwtHeader {
|
|
96
|
+
/** Algorithm (e.g., "EdDSA") */
|
|
97
|
+
alg: string;
|
|
98
|
+
/** Token type (usually "JWT") */
|
|
99
|
+
typ?: string;
|
|
100
|
+
/** Key ID - references verification method in DID document */
|
|
101
|
+
kid?: string;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* JSON Web Key structure for Ed25519 keys.
|
|
105
|
+
*/
|
|
106
|
+
export interface JsonWebKey {
|
|
107
|
+
/** Key type (always "OKP" for Ed25519) */
|
|
108
|
+
kty: string;
|
|
109
|
+
/** Curve (always "Ed25519") */
|
|
110
|
+
crv: string;
|
|
111
|
+
/** Public key material (base64url encoded) */
|
|
112
|
+
x: string;
|
|
113
|
+
/** Private key material (base64url encoded) - only present in private keys */
|
|
114
|
+
d?: string | undefined;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Key pair returned from WASM generate_keypair().
|
|
118
|
+
*/
|
|
119
|
+
export interface KeyPair {
|
|
120
|
+
/** Full JWK with private key material (keep secret!) */
|
|
121
|
+
private_key: JsonWebKey;
|
|
122
|
+
/** Public JWK (safe to share) */
|
|
123
|
+
public_key: JsonWebKey;
|
|
124
|
+
}
|
|
125
|
+
export type VcErrorCode = 'JWT_EXPIRED' | 'INVALID_JWT_FORMAT' | 'INVALID_JWK' | 'VERIFICATION_FAILED' | 'CLAIMS_VALIDATION' | 'SERIALIZATION_ERROR' | 'DECODE_ERROR' | 'KEY_GENERATION' | 'SIGNING_FAILED';
|
|
126
|
+
export interface JwtExpiredError {
|
|
127
|
+
code: 'JWT_EXPIRED';
|
|
128
|
+
message: string;
|
|
129
|
+
data: {
|
|
130
|
+
expiredAt: string;
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
export interface GenericVcError {
|
|
134
|
+
code: Exclude<VcErrorCode, 'JWT_EXPIRED'>;
|
|
135
|
+
message: string;
|
|
136
|
+
data?: undefined;
|
|
137
|
+
}
|
|
138
|
+
export type WasmVcError = JwtExpiredError | GenericVcError;
|
|
139
|
+
export declare function isWasmVcError(e: unknown): e is WasmVcError;
|
|
140
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/vc/types.ts"],"names":[],"mappings":"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"}
|
package/dist/vc/types.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 Semiotic AI, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: MIT
|
|
4
|
+
export function isWasmVcError(e) {
|
|
5
|
+
if (typeof e !== 'object' || e === null)
|
|
6
|
+
return false;
|
|
7
|
+
const anyE = e;
|
|
8
|
+
return typeof anyE.code === 'string' && typeof anyE.message === 'string';
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/vc/types.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,+BAA+B;AAgK/B,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,IAAI,GAAG,CAA0C,CAAC;IACxD,OAAO,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC;AAC3E,CAAC"}
|
package/dist/wasm.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type InitInput } from '@semiotic-labs/agentium-sdk-wasm';
|
|
2
|
+
import type { VerificationResult, KeyPair } from './vc/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Ensures the WASM module is loaded and ready.
|
|
5
|
+
* Uses lazy initialization - only loads on first call.
|
|
6
|
+
*
|
|
7
|
+
* @param wasmUrl - Optional URL/path to the WASM binary. If not provided,
|
|
8
|
+
* defaults to resolving `wasm_bg.wasm` relative to the JS module.
|
|
9
|
+
* For browser usage with bundlers like Vite, you may need:
|
|
10
|
+
* ```ts
|
|
11
|
+
* import wasmUrl from 'wasm/wasm_bg.wasm?url';
|
|
12
|
+
* await ensureWasmReady(wasmUrl);
|
|
13
|
+
* ```
|
|
14
|
+
* @returns Promise that resolves when WASM is ready
|
|
15
|
+
*/
|
|
16
|
+
export declare function ensureWasmReady(wasmUrl?: InitInput): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Initialize WASM logging to browser console.
|
|
19
|
+
* Call once after ensureWasmReady() to enable debug output.
|
|
20
|
+
*/
|
|
21
|
+
export declare function initLogging(): void;
|
|
22
|
+
/**
|
|
23
|
+
* Verify a JWT-VC against a public key.
|
|
24
|
+
*
|
|
25
|
+
* @param jwt - The JWT string to verify (compact format: header.payload.signature)
|
|
26
|
+
* @param publicKeyJwk - The public key as JWK JSON string
|
|
27
|
+
* @returns Verification result with validity status, decoded claims if valid, and structured error if invalid.
|
|
28
|
+
* On failure: `{ valid: false, error: { code, message, data? } }`.
|
|
29
|
+
* Error codes: `JWT_EXPIRED` (with `data.expiredAt`), `INVALID_JWT_FORMAT`, `INVALID_JWK`,
|
|
30
|
+
* `VERIFICATION_FAILED`, `CLAIMS_VALIDATION`, `SERIALIZATION_ERROR`, `DECODE_ERROR`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function verifyJwt(jwt: string, publicKeyJwk: string): Promise<VerificationResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Generate a new Ed25519 key pair.
|
|
35
|
+
*
|
|
36
|
+
* @returns Key pair with private and public JWK strings
|
|
37
|
+
* @throws {WasmVcError} If key generation or serialization fails.
|
|
38
|
+
*/
|
|
39
|
+
export declare function generateKeypair(): Promise<KeyPair>;
|
|
40
|
+
/**
|
|
41
|
+
* Extract public key from a private JWK.
|
|
42
|
+
*
|
|
43
|
+
* @param privateKeyJwk - The private key as JWK JSON string
|
|
44
|
+
* @returns The public key as JWK JSON string
|
|
45
|
+
* @throws {WasmVcError} If the private key JWK is invalid or serialization fails.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getPublicKey(privateKeyJwk: string): Promise<string>;
|
|
48
|
+
//# sourceMappingURL=wasm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasm.d.ts","sourceRoot":"","sources":["../src/wasm.ts"],"names":[],"mappings":"AAIA,OAAa,EAKX,KAAK,SAAS,EACf,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAKjE;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAOxE;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAKlC;AAED;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAG9F;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAGxD;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGzE"}
|
package/dist/wasm.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 Semiotic AI, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: MIT
|
|
4
|
+
import init, { verify_jwt as wasmVerifyJwt, generate_keypair as wasmGenerateKeypair, get_public_key as wasmGetPublicKey, init_logging as wasmInitLogging, } from '@semiotic-labs/agentium-sdk-wasm';
|
|
5
|
+
let wasmInitialized = null;
|
|
6
|
+
let loggingInitialized = false;
|
|
7
|
+
/**
|
|
8
|
+
* Ensures the WASM module is loaded and ready.
|
|
9
|
+
* Uses lazy initialization - only loads on first call.
|
|
10
|
+
*
|
|
11
|
+
* @param wasmUrl - Optional URL/path to the WASM binary. If not provided,
|
|
12
|
+
* defaults to resolving `wasm_bg.wasm` relative to the JS module.
|
|
13
|
+
* For browser usage with bundlers like Vite, you may need:
|
|
14
|
+
* ```ts
|
|
15
|
+
* import wasmUrl from 'wasm/wasm_bg.wasm?url';
|
|
16
|
+
* await ensureWasmReady(wasmUrl);
|
|
17
|
+
* ```
|
|
18
|
+
* @returns Promise that resolves when WASM is ready
|
|
19
|
+
*/
|
|
20
|
+
export async function ensureWasmReady(wasmUrl) {
|
|
21
|
+
if (wasmInitialized === null) {
|
|
22
|
+
wasmInitialized = init(wasmUrl).then(() => {
|
|
23
|
+
// Module loaded successfully
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
await wasmInitialized;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Initialize WASM logging to browser console.
|
|
30
|
+
* Call once after ensureWasmReady() to enable debug output.
|
|
31
|
+
*/
|
|
32
|
+
export function initLogging() {
|
|
33
|
+
if (!loggingInitialized) {
|
|
34
|
+
wasmInitLogging();
|
|
35
|
+
loggingInitialized = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Verify a JWT-VC against a public key.
|
|
40
|
+
*
|
|
41
|
+
* @param jwt - The JWT string to verify (compact format: header.payload.signature)
|
|
42
|
+
* @param publicKeyJwk - The public key as JWK JSON string
|
|
43
|
+
* @returns Verification result with validity status, decoded claims if valid, and structured error if invalid.
|
|
44
|
+
* On failure: `{ valid: false, error: { code, message, data? } }`.
|
|
45
|
+
* Error codes: `JWT_EXPIRED` (with `data.expiredAt`), `INVALID_JWT_FORMAT`, `INVALID_JWK`,
|
|
46
|
+
* `VERIFICATION_FAILED`, `CLAIMS_VALIDATION`, `SERIALIZATION_ERROR`, `DECODE_ERROR`.
|
|
47
|
+
*/
|
|
48
|
+
export async function verifyJwt(jwt, publicKeyJwk) {
|
|
49
|
+
await ensureWasmReady();
|
|
50
|
+
return wasmVerifyJwt(jwt, publicKeyJwk);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generate a new Ed25519 key pair.
|
|
54
|
+
*
|
|
55
|
+
* @returns Key pair with private and public JWK strings
|
|
56
|
+
* @throws {WasmVcError} If key generation or serialization fails.
|
|
57
|
+
*/
|
|
58
|
+
export async function generateKeypair() {
|
|
59
|
+
await ensureWasmReady();
|
|
60
|
+
return wasmGenerateKeypair();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Extract public key from a private JWK.
|
|
64
|
+
*
|
|
65
|
+
* @param privateKeyJwk - The private key as JWK JSON string
|
|
66
|
+
* @returns The public key as JWK JSON string
|
|
67
|
+
* @throws {WasmVcError} If the private key JWK is invalid or serialization fails.
|
|
68
|
+
*/
|
|
69
|
+
export async function getPublicKey(privateKeyJwk) {
|
|
70
|
+
await ensureWasmReady();
|
|
71
|
+
return wasmGetPublicKey(privateKeyJwk);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=wasm.js.map
|
package/dist/wasm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasm.js","sourceRoot":"","sources":["../src/wasm.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,+BAA+B;AAE/B,OAAO,IAAI,EAAE,EACX,UAAU,IAAI,aAAa,EAC3B,gBAAgB,IAAI,mBAAmB,EACvC,cAAc,IAAI,gBAAgB,EAClC,YAAY,IAAI,eAAe,GAEhC,MAAM,kCAAkC,CAAC;AAG1C,IAAI,eAAe,GAAyB,IAAI,CAAC;AACjD,IAAI,kBAAkB,GAAG,KAAK,CAAC;AAE/B;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAmB;IACvD,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;QAC7B,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACxC,6BAA6B;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,eAAe,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,eAAe,EAAE,CAAC;QAClB,kBAAkB,GAAG,IAAI,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,YAAoB;IAC/D,MAAM,eAAe,EAAE,CAAC;IACxB,OAAO,aAAa,CAAC,GAAG,EAAE,YAAY,CAAuB,CAAC;AAChE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,eAAe,EAAE,CAAC;IACxB,OAAO,mBAAmB,EAAa,CAAC;AAC1C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,aAAqB;IACtD,MAAM,eAAe,EAAE,CAAC;IACxB,OAAO,gBAAgB,CAAC,aAAa,CAAC,CAAC;AACzC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@semiotic-labs/agentium-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"files": [
|
|
9
|
-
"dist"
|
|
9
|
+
"dist",
|
|
10
|
+
"packages/agentium-native/wasm/pkg"
|
|
10
11
|
],
|
|
11
12
|
"scripts": {
|
|
12
13
|
"test": "vitest",
|
|
13
|
-
"build": "
|
|
14
|
+
"build:wasm": "cd packages/agentium-native/wasm && wasm-pack build --target web --scope semiotic-labs",
|
|
15
|
+
"build": "npm run build:wasm && tsc",
|
|
14
16
|
"docs": "typedoc",
|
|
15
17
|
"lint": "eslint src/**/*.ts",
|
|
16
18
|
"format:check": "prettier --check .",
|
|
@@ -42,6 +44,7 @@
|
|
|
42
44
|
"devDependencies": {
|
|
43
45
|
"@types/node": "^24.10.1",
|
|
44
46
|
"axios-mock-adapter": "^2.1.0",
|
|
47
|
+
"jose": "^6.0.10",
|
|
45
48
|
"eslint": "^9.39.1",
|
|
46
49
|
"eslint-config-prettier": "^10.1.8",
|
|
47
50
|
"eslint-plugin-prettier": "^5.5.4",
|
|
@@ -53,6 +56,7 @@
|
|
|
53
56
|
"vitest": "^4.0.15"
|
|
54
57
|
},
|
|
55
58
|
"dependencies": {
|
|
59
|
+
"@semiotic-labs/agentium-sdk-wasm": "file:./packages/agentium-native/wasm/pkg",
|
|
56
60
|
"axios": "^1.13.2"
|
|
57
61
|
}
|
|
58
62
|
}
|