@signedby/sdk 0.1.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/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # SignedByMe TypeScript SDK
2
+
3
+ Human-controlled identity for autonomous agents.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @signedby/sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### For Agents - Authenticate to Enterprises
14
+
15
+ ```typescript
16
+ import { SignedByClient } from '@signedby/sdk';
17
+
18
+ // Load delegation from your human owner
19
+ const client = await SignedByClient.fromDelegation('./delegation.json');
20
+
21
+ console.log(`Your npub: ${client.npub}`);
22
+ console.log(`Authorized for: ${JSON.stringify(client.scopes)}`);
23
+
24
+ // Authenticate to an enterprise
25
+ const token = await client.login({
26
+ clientId: 'acme-corp',
27
+ nonce: 'random_nonce_here'
28
+ });
29
+
30
+ // Use the OIDC token
31
+ console.log(`ID Token: ${token.idToken}`);
32
+ console.log(`Subject: ${token.sub}`);
33
+ ```
34
+
35
+ ### For Agent Setup - Initialize Identity
36
+
37
+ ```typescript
38
+ import { SignedByAgent } from '@signedby/sdk';
39
+
40
+ // Initialize agent (creates DID if first run)
41
+ const agent = await SignedByAgent.init('./agent_data');
42
+
43
+ console.log(`Agent npub: ${agent.npub}`);
44
+
45
+ // Configure email mapping for enterprises
46
+ agent.setEmailMapping({
47
+ 'amazon.com': 'you@gmail.com',
48
+ 'acme.com': 'you@gmail.com'
49
+ });
50
+
51
+ // Connect to relay and watch for authorizations
52
+ await agent.connectRelay('wss://relay.privacy-lion.com');
53
+
54
+ for await (const event of agent.watchForAuthorizations()) {
55
+ console.log(`New authorization from: ${event.enterprise}`);
56
+ console.log(`Scopes: ${event.scopes}`);
57
+ }
58
+ ```
59
+
60
+ ## Error Handling
61
+
62
+ ```typescript
63
+ import {
64
+ SignedByClient,
65
+ SignedByError,
66
+ DelegationRevokedError,
67
+ DelegationExpiredError,
68
+ ScopeDeniedError,
69
+ } from '@signedby/sdk';
70
+
71
+ try {
72
+ const token = await client.login({ clientId: 'acme-corp', nonce });
73
+ } catch (error) {
74
+ if (error instanceof DelegationRevokedError) {
75
+ console.log('Delegation was revoked. Contact your human owner.');
76
+ } else if (error instanceof DelegationExpiredError) {
77
+ console.log('Delegation expired. Request renewal from your human owner.');
78
+ } else if (error instanceof ScopeDeniedError) {
79
+ console.log('Not authorized for this enterprise.');
80
+ } else if (error instanceof SignedByError) {
81
+ console.log(`Authentication failed: ${error.message}`);
82
+ }
83
+ }
84
+ ```
85
+
86
+ ## Requirements
87
+
88
+ - Node.js 18+
89
+ - Supported platforms: Linux (x86_64, arm64), macOS (x86_64, arm64), Windows (x86_64)
90
+
91
+ ## Documentation
92
+
93
+ - [SDK Quick Start](https://signedbyme.com/docs/sdk-quickstart.html)
94
+ - [API Reference](https://signedbyme.com/docs/api-reference.html)
95
+ - [Understanding Delegation](https://signedbyme.com/docs/delegation.html)
96
+
97
+ ## License
98
+
99
+ SignedByMe Source-Available License v1.0 (SSAL-1.0)
100
+
101
+ See [LICENSE](https://github.com/PrivacyLion/SignedByMe/blob/main/LICENSE) for details.
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Type definitions for SignedByMe SDK.
3
+ */
4
+ /**
5
+ * OIDC token returned from successful authentication.
6
+ */
7
+ interface LoginToken {
8
+ /** The OIDC id_token (JWT) */
9
+ idToken: string;
10
+ /** Token type, always "Bearer" */
11
+ tokenType: string;
12
+ /** Seconds until token expires */
13
+ expiresIn: number;
14
+ /** Subject - agent's npub in bech32 format */
15
+ sub: string;
16
+ }
17
+ /**
18
+ * Request parameters for login.
19
+ */
20
+ interface LoginRequest {
21
+ /** Enterprise client ID */
22
+ clientId: string;
23
+ /** Random nonce for replay protection */
24
+ nonce: string;
25
+ }
26
+ /**
27
+ * Delegation scopes mapping enterprise to permissions.
28
+ */
29
+ type Scopes = Record<string, string[]>;
30
+ /**
31
+ * An authorization request from an enterprise (kind 28200).
32
+ */
33
+ interface AuthorizationEvent {
34
+ /** Enterprise name/domain */
35
+ enterprise: string;
36
+ /** Enterprise client ID */
37
+ clientId: string;
38
+ /** Offered permission scopes */
39
+ scopes: string[];
40
+ /** NOSTR event ID */
41
+ eventId: string;
42
+ /** Unix timestamp of event creation */
43
+ createdAt: number;
44
+ }
45
+ /**
46
+ * Login options for customizing authentication.
47
+ */
48
+ interface LoginOptions {
49
+ /** NOSTR relay URL (default: wss://relay.privacy-lion.com) */
50
+ relayUrl?: string;
51
+ /** SignedByMe API URL (default: https://api.beta.privacy-lion.com) */
52
+ apiUrl?: string;
53
+ }
54
+
55
+ /**
56
+ * SignedByClient - Core client for agent authentication.
57
+ */
58
+
59
+ /**
60
+ * Client for authenticating to enterprises using SignedByMe.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const client = await SignedByClient.fromDelegation('./delegation.json');
65
+ * const token = await client.login({
66
+ * clientId: 'acme-corp',
67
+ * nonce: 'random123'
68
+ * });
69
+ * console.log(`ID Token: ${token.idToken}`);
70
+ * ```
71
+ */
72
+ declare class SignedByClient {
73
+ private readonly nativeClient;
74
+ private readonly delegation;
75
+ private constructor();
76
+ /**
77
+ * Load a SignedByClient from a delegation file.
78
+ *
79
+ * @param path - Path to the delegation JSON file (kind 28250 event)
80
+ * @returns SignedByClient instance ready for authentication
81
+ * @throws {Error} If delegation file doesn't exist or is invalid
82
+ */
83
+ static fromDelegation(path: string): Promise<SignedByClient>;
84
+ /**
85
+ * Get the agent's npub (public key in bech32 format).
86
+ */
87
+ get npub(): string;
88
+ /**
89
+ * Get the delegation scopes (enterprise -> permissions mapping).
90
+ */
91
+ get scopes(): Scopes;
92
+ /**
93
+ * Authenticate to an enterprise and receive an OIDC token.
94
+ *
95
+ * @param request - Login request parameters
96
+ * @param options - Optional configuration
97
+ * @returns LoginToken containing the OIDC id_token
98
+ * @throws {DelegationRevokedError} If delegation has been revoked
99
+ * @throws {DelegationExpiredError} If delegation has expired
100
+ * @throws {ScopeDeniedError} If client_id not in delegation scopes
101
+ * @throws {MerkleRootExpiredError} If proof uses stale merkle root
102
+ */
103
+ login(request: LoginRequest, options?: LoginOptions): Promise<LoginToken>;
104
+ }
105
+
106
+ /**
107
+ * SignedByAgent - Agent initialization and management.
108
+ */
109
+
110
+ /**
111
+ * Agent for managing identity and watching for authorization requests.
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * const agent = await SignedByAgent.init('./agent_data');
116
+ * agent.setEmailMapping({
117
+ * 'amazon.com': 'me@gmail.com',
118
+ * 'acme.com': 'me@gmail.com'
119
+ * });
120
+ * await agent.connectRelay('wss://relay.privacy-lion.com');
121
+ * agent.watchForAuthorizations();
122
+ * ```
123
+ */
124
+ declare class SignedByAgent {
125
+ private readonly nativeAgent;
126
+ private relayConnected;
127
+ private _emailMapping;
128
+ private constructor();
129
+ /**
130
+ * Initialize a new agent or load existing identity.
131
+ *
132
+ * Creates DID keys and stores them securely if this is first run.
133
+ * Loads existing identity if storage already exists.
134
+ *
135
+ * @param storagePath - Directory for agent data (keys, witness cache)
136
+ * @returns SignedByAgent instance
137
+ */
138
+ static init(storagePath: string): Promise<SignedByAgent>;
139
+ /**
140
+ * Get the agent's npub (public key in bech32 format).
141
+ */
142
+ get npub(): string;
143
+ /**
144
+ * Set email mapping for enterprises.
145
+ *
146
+ * This tells the agent which email to provide during Gate 1
147
+ * enrollment for each enterprise domain.
148
+ *
149
+ * @param mapping - Dict of enterprise domain -> email address
150
+ */
151
+ setEmailMapping(mapping: Record<string, string>): void;
152
+ /**
153
+ * Connect to a NOSTR relay.
154
+ *
155
+ * @param relayUrl - WebSocket URL of the relay
156
+ */
157
+ connectRelay(relayUrl: string): Promise<void>;
158
+ /**
159
+ * Watch for kind 28200 authorization events addressed to this agent.
160
+ *
161
+ * @yields AuthorizationEvent for each incoming authorization request
162
+ */
163
+ watchForAuthorizations(): AsyncGenerator<AuthorizationEvent>;
164
+ /**
165
+ * Get recent agent activity (kinds 28101, 28102, 28103).
166
+ *
167
+ * @param limit - Maximum number of events to return
168
+ * @returns List of activity events
169
+ */
170
+ getActivityLog(limit?: number): Array<Record<string, unknown>>;
171
+ }
172
+
173
+ /**
174
+ * SignedByMe SDK Errors.
175
+ */
176
+ /**
177
+ * Base error class for all SignedByMe errors.
178
+ */
179
+ declare class SignedByError extends Error {
180
+ constructor(message: string);
181
+ }
182
+ /**
183
+ * Raised when the delegation has been revoked.
184
+ *
185
+ * The human owner published a kind 28251 revocation event.
186
+ * Contact your human owner for a new delegation.
187
+ */
188
+ declare class DelegationRevokedError extends SignedByError {
189
+ constructor(message?: string);
190
+ }
191
+ /**
192
+ * Raised when the delegation has expired.
193
+ *
194
+ * The expires_at timestamp in the delegation has passed.
195
+ * Request a renewed delegation from your human owner.
196
+ */
197
+ declare class DelegationExpiredError extends SignedByError {
198
+ constructor(message?: string);
199
+ }
200
+ /**
201
+ * Raised when Groth16 proof verification fails.
202
+ *
203
+ * This typically indicates corrupted proof data or
204
+ * a mismatch between proof and public inputs.
205
+ */
206
+ declare class InvalidProofError extends SignedByError {
207
+ constructor(message?: string);
208
+ }
209
+ /**
210
+ * Raised when the proof references a stale merkle root.
211
+ *
212
+ * The merkle root in the proof is not in the last 30 valid roots.
213
+ * Refresh witness data and regenerate the proof.
214
+ */
215
+ declare class MerkleRootExpiredError extends SignedByError {
216
+ constructor(message?: string);
217
+ }
218
+ /**
219
+ * Raised when attempting to access an unauthorized enterprise.
220
+ *
221
+ * The client_id is not in the delegation scopes.
222
+ * Request an updated delegation that includes this enterprise.
223
+ */
224
+ declare class ScopeDeniedError extends SignedByError {
225
+ constructor(message?: string);
226
+ }
227
+ /**
228
+ * Raised when unable to connect to a NOSTR relay.
229
+ */
230
+ declare class RelayConnectionError extends SignedByError {
231
+ constructor(message?: string);
232
+ }
233
+ /**
234
+ * Raised when the SignedByMe API returns an error.
235
+ */
236
+ declare class ApiError extends SignedByError {
237
+ readonly errorCode?: string;
238
+ readonly statusCode?: number;
239
+ constructor(message: string, errorCode?: string, statusCode?: number);
240
+ }
241
+
242
+ export { ApiError, type AuthorizationEvent, DelegationExpiredError, DelegationRevokedError, InvalidProofError, type LoginRequest, type LoginToken, MerkleRootExpiredError, RelayConnectionError, ScopeDeniedError, type Scopes, SignedByAgent, SignedByClient, SignedByError };
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Type definitions for SignedByMe SDK.
3
+ */
4
+ /**
5
+ * OIDC token returned from successful authentication.
6
+ */
7
+ interface LoginToken {
8
+ /** The OIDC id_token (JWT) */
9
+ idToken: string;
10
+ /** Token type, always "Bearer" */
11
+ tokenType: string;
12
+ /** Seconds until token expires */
13
+ expiresIn: number;
14
+ /** Subject - agent's npub in bech32 format */
15
+ sub: string;
16
+ }
17
+ /**
18
+ * Request parameters for login.
19
+ */
20
+ interface LoginRequest {
21
+ /** Enterprise client ID */
22
+ clientId: string;
23
+ /** Random nonce for replay protection */
24
+ nonce: string;
25
+ }
26
+ /**
27
+ * Delegation scopes mapping enterprise to permissions.
28
+ */
29
+ type Scopes = Record<string, string[]>;
30
+ /**
31
+ * An authorization request from an enterprise (kind 28200).
32
+ */
33
+ interface AuthorizationEvent {
34
+ /** Enterprise name/domain */
35
+ enterprise: string;
36
+ /** Enterprise client ID */
37
+ clientId: string;
38
+ /** Offered permission scopes */
39
+ scopes: string[];
40
+ /** NOSTR event ID */
41
+ eventId: string;
42
+ /** Unix timestamp of event creation */
43
+ createdAt: number;
44
+ }
45
+ /**
46
+ * Login options for customizing authentication.
47
+ */
48
+ interface LoginOptions {
49
+ /** NOSTR relay URL (default: wss://relay.privacy-lion.com) */
50
+ relayUrl?: string;
51
+ /** SignedByMe API URL (default: https://api.beta.privacy-lion.com) */
52
+ apiUrl?: string;
53
+ }
54
+
55
+ /**
56
+ * SignedByClient - Core client for agent authentication.
57
+ */
58
+
59
+ /**
60
+ * Client for authenticating to enterprises using SignedByMe.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const client = await SignedByClient.fromDelegation('./delegation.json');
65
+ * const token = await client.login({
66
+ * clientId: 'acme-corp',
67
+ * nonce: 'random123'
68
+ * });
69
+ * console.log(`ID Token: ${token.idToken}`);
70
+ * ```
71
+ */
72
+ declare class SignedByClient {
73
+ private readonly nativeClient;
74
+ private readonly delegation;
75
+ private constructor();
76
+ /**
77
+ * Load a SignedByClient from a delegation file.
78
+ *
79
+ * @param path - Path to the delegation JSON file (kind 28250 event)
80
+ * @returns SignedByClient instance ready for authentication
81
+ * @throws {Error} If delegation file doesn't exist or is invalid
82
+ */
83
+ static fromDelegation(path: string): Promise<SignedByClient>;
84
+ /**
85
+ * Get the agent's npub (public key in bech32 format).
86
+ */
87
+ get npub(): string;
88
+ /**
89
+ * Get the delegation scopes (enterprise -> permissions mapping).
90
+ */
91
+ get scopes(): Scopes;
92
+ /**
93
+ * Authenticate to an enterprise and receive an OIDC token.
94
+ *
95
+ * @param request - Login request parameters
96
+ * @param options - Optional configuration
97
+ * @returns LoginToken containing the OIDC id_token
98
+ * @throws {DelegationRevokedError} If delegation has been revoked
99
+ * @throws {DelegationExpiredError} If delegation has expired
100
+ * @throws {ScopeDeniedError} If client_id not in delegation scopes
101
+ * @throws {MerkleRootExpiredError} If proof uses stale merkle root
102
+ */
103
+ login(request: LoginRequest, options?: LoginOptions): Promise<LoginToken>;
104
+ }
105
+
106
+ /**
107
+ * SignedByAgent - Agent initialization and management.
108
+ */
109
+
110
+ /**
111
+ * Agent for managing identity and watching for authorization requests.
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * const agent = await SignedByAgent.init('./agent_data');
116
+ * agent.setEmailMapping({
117
+ * 'amazon.com': 'me@gmail.com',
118
+ * 'acme.com': 'me@gmail.com'
119
+ * });
120
+ * await agent.connectRelay('wss://relay.privacy-lion.com');
121
+ * agent.watchForAuthorizations();
122
+ * ```
123
+ */
124
+ declare class SignedByAgent {
125
+ private readonly nativeAgent;
126
+ private relayConnected;
127
+ private _emailMapping;
128
+ private constructor();
129
+ /**
130
+ * Initialize a new agent or load existing identity.
131
+ *
132
+ * Creates DID keys and stores them securely if this is first run.
133
+ * Loads existing identity if storage already exists.
134
+ *
135
+ * @param storagePath - Directory for agent data (keys, witness cache)
136
+ * @returns SignedByAgent instance
137
+ */
138
+ static init(storagePath: string): Promise<SignedByAgent>;
139
+ /**
140
+ * Get the agent's npub (public key in bech32 format).
141
+ */
142
+ get npub(): string;
143
+ /**
144
+ * Set email mapping for enterprises.
145
+ *
146
+ * This tells the agent which email to provide during Gate 1
147
+ * enrollment for each enterprise domain.
148
+ *
149
+ * @param mapping - Dict of enterprise domain -> email address
150
+ */
151
+ setEmailMapping(mapping: Record<string, string>): void;
152
+ /**
153
+ * Connect to a NOSTR relay.
154
+ *
155
+ * @param relayUrl - WebSocket URL of the relay
156
+ */
157
+ connectRelay(relayUrl: string): Promise<void>;
158
+ /**
159
+ * Watch for kind 28200 authorization events addressed to this agent.
160
+ *
161
+ * @yields AuthorizationEvent for each incoming authorization request
162
+ */
163
+ watchForAuthorizations(): AsyncGenerator<AuthorizationEvent>;
164
+ /**
165
+ * Get recent agent activity (kinds 28101, 28102, 28103).
166
+ *
167
+ * @param limit - Maximum number of events to return
168
+ * @returns List of activity events
169
+ */
170
+ getActivityLog(limit?: number): Array<Record<string, unknown>>;
171
+ }
172
+
173
+ /**
174
+ * SignedByMe SDK Errors.
175
+ */
176
+ /**
177
+ * Base error class for all SignedByMe errors.
178
+ */
179
+ declare class SignedByError extends Error {
180
+ constructor(message: string);
181
+ }
182
+ /**
183
+ * Raised when the delegation has been revoked.
184
+ *
185
+ * The human owner published a kind 28251 revocation event.
186
+ * Contact your human owner for a new delegation.
187
+ */
188
+ declare class DelegationRevokedError extends SignedByError {
189
+ constructor(message?: string);
190
+ }
191
+ /**
192
+ * Raised when the delegation has expired.
193
+ *
194
+ * The expires_at timestamp in the delegation has passed.
195
+ * Request a renewed delegation from your human owner.
196
+ */
197
+ declare class DelegationExpiredError extends SignedByError {
198
+ constructor(message?: string);
199
+ }
200
+ /**
201
+ * Raised when Groth16 proof verification fails.
202
+ *
203
+ * This typically indicates corrupted proof data or
204
+ * a mismatch between proof and public inputs.
205
+ */
206
+ declare class InvalidProofError extends SignedByError {
207
+ constructor(message?: string);
208
+ }
209
+ /**
210
+ * Raised when the proof references a stale merkle root.
211
+ *
212
+ * The merkle root in the proof is not in the last 30 valid roots.
213
+ * Refresh witness data and regenerate the proof.
214
+ */
215
+ declare class MerkleRootExpiredError extends SignedByError {
216
+ constructor(message?: string);
217
+ }
218
+ /**
219
+ * Raised when attempting to access an unauthorized enterprise.
220
+ *
221
+ * The client_id is not in the delegation scopes.
222
+ * Request an updated delegation that includes this enterprise.
223
+ */
224
+ declare class ScopeDeniedError extends SignedByError {
225
+ constructor(message?: string);
226
+ }
227
+ /**
228
+ * Raised when unable to connect to a NOSTR relay.
229
+ */
230
+ declare class RelayConnectionError extends SignedByError {
231
+ constructor(message?: string);
232
+ }
233
+ /**
234
+ * Raised when the SignedByMe API returns an error.
235
+ */
236
+ declare class ApiError extends SignedByError {
237
+ readonly errorCode?: string;
238
+ readonly statusCode?: number;
239
+ constructor(message: string, errorCode?: string, statusCode?: number);
240
+ }
241
+
242
+ export { ApiError, type AuthorizationEvent, DelegationExpiredError, DelegationRevokedError, InvalidProofError, type LoginRequest, type LoginToken, MerkleRootExpiredError, RelayConnectionError, ScopeDeniedError, type Scopes, SignedByAgent, SignedByClient, SignedByError };
package/dist/index.js ADDED
@@ -0,0 +1,320 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __commonJS = (cb, mod) => function __require() {
7
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
8
+ };
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+
23
+ // src/native.ts
24
+ var require_native = __commonJS({
25
+ "src/native.ts"(exports2, module2) {
26
+ "use strict";
27
+ var import_os = require("os");
28
+ var import_path = require("path");
29
+ function loadNativeBinding() {
30
+ const platformName = (0, import_os.platform)();
31
+ const archName = (0, import_os.arch)();
32
+ let nativeBinding;
33
+ const platformMap = {
34
+ darwin: {
35
+ x64: "@signedby/core-darwin-x64",
36
+ arm64: "@signedby/core-darwin-arm64"
37
+ },
38
+ linux: {
39
+ x64: "@signedby/core-linux-x64-gnu",
40
+ arm64: "@signedby/core-linux-arm64-gnu"
41
+ },
42
+ win32: {
43
+ x64: "@signedby/core-win32-x64-msvc"
44
+ }
45
+ };
46
+ const packageName = platformMap[platformName]?.[archName];
47
+ if (!packageName) {
48
+ throw new Error(
49
+ `Unsupported platform: ${platformName}-${archName}. SignedByMe SDK supports: linux-x64, linux-arm64, darwin-x64, darwin-arm64, win32-x64`
50
+ );
51
+ }
52
+ try {
53
+ nativeBinding = require(packageName);
54
+ } catch (loadError) {
55
+ try {
56
+ nativeBinding = require((0, import_path.join)(__dirname, "..", "native", `signedby_core.${platformName}.node`));
57
+ } catch {
58
+ throw new Error(
59
+ `Failed to load native module for ${platformName}-${archName}. Install with: npm install ${packageName}
60
+ Original error: ${loadError}`
61
+ );
62
+ }
63
+ }
64
+ return nativeBinding;
65
+ }
66
+ module2.exports = loadNativeBinding();
67
+ }
68
+ });
69
+
70
+ // src/index.ts
71
+ var index_exports = {};
72
+ __export(index_exports, {
73
+ ApiError: () => ApiError,
74
+ DelegationExpiredError: () => DelegationExpiredError,
75
+ DelegationRevokedError: () => DelegationRevokedError,
76
+ InvalidProofError: () => InvalidProofError,
77
+ MerkleRootExpiredError: () => MerkleRootExpiredError,
78
+ RelayConnectionError: () => RelayConnectionError,
79
+ ScopeDeniedError: () => ScopeDeniedError,
80
+ SignedByAgent: () => SignedByAgent,
81
+ SignedByClient: () => SignedByClient,
82
+ SignedByError: () => SignedByError
83
+ });
84
+ module.exports = __toCommonJS(index_exports);
85
+
86
+ // src/client.ts
87
+ var import_fs = require("fs");
88
+
89
+ // src/errors.ts
90
+ var SignedByError = class extends Error {
91
+ constructor(message) {
92
+ super(message);
93
+ this.name = "SignedByError";
94
+ }
95
+ };
96
+ var DelegationRevokedError = class extends SignedByError {
97
+ constructor(message = "Delegation has been revoked") {
98
+ super(message);
99
+ this.name = "DelegationRevokedError";
100
+ }
101
+ };
102
+ var DelegationExpiredError = class extends SignedByError {
103
+ constructor(message = "Delegation has expired") {
104
+ super(message);
105
+ this.name = "DelegationExpiredError";
106
+ }
107
+ };
108
+ var InvalidProofError = class extends SignedByError {
109
+ constructor(message = "Invalid Groth16 proof") {
110
+ super(message);
111
+ this.name = "InvalidProofError";
112
+ }
113
+ };
114
+ var MerkleRootExpiredError = class extends SignedByError {
115
+ constructor(message = "Merkle root is expired") {
116
+ super(message);
117
+ this.name = "MerkleRootExpiredError";
118
+ }
119
+ };
120
+ var ScopeDeniedError = class extends SignedByError {
121
+ constructor(message = "Enterprise not in delegation scopes") {
122
+ super(message);
123
+ this.name = "ScopeDeniedError";
124
+ }
125
+ };
126
+ var RelayConnectionError = class extends SignedByError {
127
+ constructor(message = "Failed to connect to relay") {
128
+ super(message);
129
+ this.name = "RelayConnectionError";
130
+ }
131
+ };
132
+ var ApiError = class extends SignedByError {
133
+ errorCode;
134
+ statusCode;
135
+ constructor(message, errorCode, statusCode) {
136
+ super(message);
137
+ this.name = "ApiError";
138
+ this.errorCode = errorCode;
139
+ this.statusCode = statusCode;
140
+ }
141
+ };
142
+
143
+ // src/client.ts
144
+ var native = require_native();
145
+ var DEFAULT_RELAY_URL = "wss://relay.privacy-lion.com";
146
+ var DEFAULT_API_URL = "https://api.beta.privacy-lion.com";
147
+ var SignedByClient = class _SignedByClient {
148
+ nativeClient;
149
+ delegation;
150
+ constructor(nativeClient, delegation) {
151
+ this.nativeClient = nativeClient;
152
+ this.delegation = delegation;
153
+ }
154
+ /**
155
+ * Load a SignedByClient from a delegation file.
156
+ *
157
+ * @param path - Path to the delegation JSON file (kind 28250 event)
158
+ * @returns SignedByClient instance ready for authentication
159
+ * @throws {Error} If delegation file doesn't exist or is invalid
160
+ */
161
+ static async fromDelegation(path) {
162
+ const delegationJson = (0, import_fs.readFileSync)(path, "utf-8");
163
+ const event = JSON.parse(delegationJson);
164
+ const content = JSON.parse(event.content);
165
+ const expiresAt = new Date(content.expiresAt);
166
+ if (expiresAt < /* @__PURE__ */ new Date()) {
167
+ throw new DelegationExpiredError();
168
+ }
169
+ const nativeClient = await native.SignedByClient.fromDelegationJson(delegationJson);
170
+ return new _SignedByClient(nativeClient, content);
171
+ }
172
+ /**
173
+ * Get the agent's npub (public key in bech32 format).
174
+ */
175
+ get npub() {
176
+ return native.getNpub(this.nativeClient);
177
+ }
178
+ /**
179
+ * Get the delegation scopes (enterprise -> permissions mapping).
180
+ */
181
+ get scopes() {
182
+ return this.delegation.scopes;
183
+ }
184
+ /**
185
+ * Authenticate to an enterprise and receive an OIDC token.
186
+ *
187
+ * @param request - Login request parameters
188
+ * @param options - Optional configuration
189
+ * @returns LoginToken containing the OIDC id_token
190
+ * @throws {DelegationRevokedError} If delegation has been revoked
191
+ * @throws {DelegationExpiredError} If delegation has expired
192
+ * @throws {ScopeDeniedError} If client_id not in delegation scopes
193
+ * @throws {MerkleRootExpiredError} If proof uses stale merkle root
194
+ */
195
+ async login(request, options = {}) {
196
+ const { clientId, nonce } = request;
197
+ const relayUrl = options.relayUrl ?? DEFAULT_RELAY_URL;
198
+ const apiUrl = options.apiUrl ?? DEFAULT_API_URL;
199
+ if (!this.scopes[clientId] && !Object.keys(this.scopes).some((k) => clientId.includes(k))) {
200
+ throw new ScopeDeniedError(`Not authorized for enterprise: ${clientId}`);
201
+ }
202
+ const proofResult = await native.generateLoginProof(this.nativeClient, clientId, nonce);
203
+ await native.publishProofEvent(this.nativeClient, relayUrl, proofResult);
204
+ const tokenResponse = await native.verifyAndGetToken(
205
+ this.nativeClient,
206
+ apiUrl,
207
+ proofResult,
208
+ clientId,
209
+ nonce
210
+ );
211
+ return {
212
+ idToken: tokenResponse.id_token,
213
+ tokenType: tokenResponse.token_type ?? "Bearer",
214
+ expiresIn: tokenResponse.expires_in ?? 3600,
215
+ sub: tokenResponse.sub
216
+ };
217
+ }
218
+ };
219
+
220
+ // src/agent.ts
221
+ var import_fs2 = require("fs");
222
+ var native2 = require_native();
223
+ var SignedByAgent = class _SignedByAgent {
224
+ nativeAgent;
225
+ relayConnected = false;
226
+ _emailMapping = {};
227
+ constructor(nativeAgent) {
228
+ this.nativeAgent = nativeAgent;
229
+ }
230
+ /**
231
+ * Initialize a new agent or load existing identity.
232
+ *
233
+ * Creates DID keys and stores them securely if this is first run.
234
+ * Loads existing identity if storage already exists.
235
+ *
236
+ * @param storagePath - Directory for agent data (keys, witness cache)
237
+ * @returns SignedByAgent instance
238
+ */
239
+ static async init(storagePath) {
240
+ if (!(0, import_fs2.existsSync)(storagePath)) {
241
+ (0, import_fs2.mkdirSync)(storagePath, { recursive: true });
242
+ }
243
+ const nativeAgent = await native2.SignedByAgent.init(storagePath);
244
+ return new _SignedByAgent(nativeAgent);
245
+ }
246
+ /**
247
+ * Get the agent's npub (public key in bech32 format).
248
+ */
249
+ get npub() {
250
+ return native2.getAgentNpub(this.nativeAgent);
251
+ }
252
+ /**
253
+ * Set email mapping for enterprises.
254
+ *
255
+ * This tells the agent which email to provide during Gate 1
256
+ * enrollment for each enterprise domain.
257
+ *
258
+ * @param mapping - Dict of enterprise domain -> email address
259
+ */
260
+ setEmailMapping(mapping) {
261
+ this._emailMapping = mapping;
262
+ native2.setEmailMapping(this.nativeAgent, mapping);
263
+ }
264
+ /**
265
+ * Connect to a NOSTR relay.
266
+ *
267
+ * @param relayUrl - WebSocket URL of the relay
268
+ */
269
+ async connectRelay(relayUrl) {
270
+ try {
271
+ await native2.connectRelay(this.nativeAgent, relayUrl);
272
+ this.relayConnected = true;
273
+ } catch (error) {
274
+ throw new RelayConnectionError(`Failed to connect to ${relayUrl}: ${error}`);
275
+ }
276
+ }
277
+ /**
278
+ * Watch for kind 28200 authorization events addressed to this agent.
279
+ *
280
+ * @yields AuthorizationEvent for each incoming authorization request
281
+ */
282
+ async *watchForAuthorizations() {
283
+ if (!this.relayConnected) {
284
+ throw new Error("Not connected to relay. Call connectRelay() first.");
285
+ }
286
+ const eventIterator = native2.subscribeAuthorizations(this.nativeAgent);
287
+ for await (const eventJson of eventIterator) {
288
+ const event = JSON.parse(eventJson);
289
+ yield {
290
+ enterprise: event.enterprise ?? "unknown",
291
+ clientId: event.client_id,
292
+ scopes: event.scopes ?? [],
293
+ eventId: event.id,
294
+ createdAt: event.created_at
295
+ };
296
+ }
297
+ }
298
+ /**
299
+ * Get recent agent activity (kinds 28101, 28102, 28103).
300
+ *
301
+ * @param limit - Maximum number of events to return
302
+ * @returns List of activity events
303
+ */
304
+ getActivityLog(limit = 100) {
305
+ return native2.getActivityLog(this.nativeAgent, limit);
306
+ }
307
+ };
308
+ // Annotate the CommonJS export names for ESM import in node:
309
+ 0 && (module.exports = {
310
+ ApiError,
311
+ DelegationExpiredError,
312
+ DelegationRevokedError,
313
+ InvalidProofError,
314
+ MerkleRootExpiredError,
315
+ RelayConnectionError,
316
+ ScopeDeniedError,
317
+ SignedByAgent,
318
+ SignedByClient,
319
+ SignedByError
320
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,292 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
+ }) : x)(function(x) {
5
+ if (typeof require !== "undefined") return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+ var __commonJS = (cb, mod) => function __require2() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+
12
+ // src/native.ts
13
+ import { platform, arch } from "os";
14
+ import { join } from "path";
15
+ var require_native = __commonJS({
16
+ "src/native.ts"(exports, module) {
17
+ "use strict";
18
+ function loadNativeBinding() {
19
+ const platformName = platform();
20
+ const archName = arch();
21
+ let nativeBinding;
22
+ const platformMap = {
23
+ darwin: {
24
+ x64: "@signedby/core-darwin-x64",
25
+ arm64: "@signedby/core-darwin-arm64"
26
+ },
27
+ linux: {
28
+ x64: "@signedby/core-linux-x64-gnu",
29
+ arm64: "@signedby/core-linux-arm64-gnu"
30
+ },
31
+ win32: {
32
+ x64: "@signedby/core-win32-x64-msvc"
33
+ }
34
+ };
35
+ const packageName = platformMap[platformName]?.[archName];
36
+ if (!packageName) {
37
+ throw new Error(
38
+ `Unsupported platform: ${platformName}-${archName}. SignedByMe SDK supports: linux-x64, linux-arm64, darwin-x64, darwin-arm64, win32-x64`
39
+ );
40
+ }
41
+ try {
42
+ nativeBinding = __require(packageName);
43
+ } catch (loadError) {
44
+ try {
45
+ nativeBinding = __require(join(__dirname, "..", "native", `signedby_core.${platformName}.node`));
46
+ } catch {
47
+ throw new Error(
48
+ `Failed to load native module for ${platformName}-${archName}. Install with: npm install ${packageName}
49
+ Original error: ${loadError}`
50
+ );
51
+ }
52
+ }
53
+ return nativeBinding;
54
+ }
55
+ module.exports = loadNativeBinding();
56
+ }
57
+ });
58
+
59
+ // src/client.ts
60
+ import { readFileSync } from "fs";
61
+
62
+ // src/errors.ts
63
+ var SignedByError = class extends Error {
64
+ constructor(message) {
65
+ super(message);
66
+ this.name = "SignedByError";
67
+ }
68
+ };
69
+ var DelegationRevokedError = class extends SignedByError {
70
+ constructor(message = "Delegation has been revoked") {
71
+ super(message);
72
+ this.name = "DelegationRevokedError";
73
+ }
74
+ };
75
+ var DelegationExpiredError = class extends SignedByError {
76
+ constructor(message = "Delegation has expired") {
77
+ super(message);
78
+ this.name = "DelegationExpiredError";
79
+ }
80
+ };
81
+ var InvalidProofError = class extends SignedByError {
82
+ constructor(message = "Invalid Groth16 proof") {
83
+ super(message);
84
+ this.name = "InvalidProofError";
85
+ }
86
+ };
87
+ var MerkleRootExpiredError = class extends SignedByError {
88
+ constructor(message = "Merkle root is expired") {
89
+ super(message);
90
+ this.name = "MerkleRootExpiredError";
91
+ }
92
+ };
93
+ var ScopeDeniedError = class extends SignedByError {
94
+ constructor(message = "Enterprise not in delegation scopes") {
95
+ super(message);
96
+ this.name = "ScopeDeniedError";
97
+ }
98
+ };
99
+ var RelayConnectionError = class extends SignedByError {
100
+ constructor(message = "Failed to connect to relay") {
101
+ super(message);
102
+ this.name = "RelayConnectionError";
103
+ }
104
+ };
105
+ var ApiError = class extends SignedByError {
106
+ errorCode;
107
+ statusCode;
108
+ constructor(message, errorCode, statusCode) {
109
+ super(message);
110
+ this.name = "ApiError";
111
+ this.errorCode = errorCode;
112
+ this.statusCode = statusCode;
113
+ }
114
+ };
115
+
116
+ // src/client.ts
117
+ var native = require_native();
118
+ var DEFAULT_RELAY_URL = "wss://relay.privacy-lion.com";
119
+ var DEFAULT_API_URL = "https://api.beta.privacy-lion.com";
120
+ var SignedByClient = class _SignedByClient {
121
+ nativeClient;
122
+ delegation;
123
+ constructor(nativeClient, delegation) {
124
+ this.nativeClient = nativeClient;
125
+ this.delegation = delegation;
126
+ }
127
+ /**
128
+ * Load a SignedByClient from a delegation file.
129
+ *
130
+ * @param path - Path to the delegation JSON file (kind 28250 event)
131
+ * @returns SignedByClient instance ready for authentication
132
+ * @throws {Error} If delegation file doesn't exist or is invalid
133
+ */
134
+ static async fromDelegation(path) {
135
+ const delegationJson = readFileSync(path, "utf-8");
136
+ const event = JSON.parse(delegationJson);
137
+ const content = JSON.parse(event.content);
138
+ const expiresAt = new Date(content.expiresAt);
139
+ if (expiresAt < /* @__PURE__ */ new Date()) {
140
+ throw new DelegationExpiredError();
141
+ }
142
+ const nativeClient = await native.SignedByClient.fromDelegationJson(delegationJson);
143
+ return new _SignedByClient(nativeClient, content);
144
+ }
145
+ /**
146
+ * Get the agent's npub (public key in bech32 format).
147
+ */
148
+ get npub() {
149
+ return native.getNpub(this.nativeClient);
150
+ }
151
+ /**
152
+ * Get the delegation scopes (enterprise -> permissions mapping).
153
+ */
154
+ get scopes() {
155
+ return this.delegation.scopes;
156
+ }
157
+ /**
158
+ * Authenticate to an enterprise and receive an OIDC token.
159
+ *
160
+ * @param request - Login request parameters
161
+ * @param options - Optional configuration
162
+ * @returns LoginToken containing the OIDC id_token
163
+ * @throws {DelegationRevokedError} If delegation has been revoked
164
+ * @throws {DelegationExpiredError} If delegation has expired
165
+ * @throws {ScopeDeniedError} If client_id not in delegation scopes
166
+ * @throws {MerkleRootExpiredError} If proof uses stale merkle root
167
+ */
168
+ async login(request, options = {}) {
169
+ const { clientId, nonce } = request;
170
+ const relayUrl = options.relayUrl ?? DEFAULT_RELAY_URL;
171
+ const apiUrl = options.apiUrl ?? DEFAULT_API_URL;
172
+ if (!this.scopes[clientId] && !Object.keys(this.scopes).some((k) => clientId.includes(k))) {
173
+ throw new ScopeDeniedError(`Not authorized for enterprise: ${clientId}`);
174
+ }
175
+ const proofResult = await native.generateLoginProof(this.nativeClient, clientId, nonce);
176
+ await native.publishProofEvent(this.nativeClient, relayUrl, proofResult);
177
+ const tokenResponse = await native.verifyAndGetToken(
178
+ this.nativeClient,
179
+ apiUrl,
180
+ proofResult,
181
+ clientId,
182
+ nonce
183
+ );
184
+ return {
185
+ idToken: tokenResponse.id_token,
186
+ tokenType: tokenResponse.token_type ?? "Bearer",
187
+ expiresIn: tokenResponse.expires_in ?? 3600,
188
+ sub: tokenResponse.sub
189
+ };
190
+ }
191
+ };
192
+
193
+ // src/agent.ts
194
+ import { mkdirSync, existsSync } from "fs";
195
+ var native2 = require_native();
196
+ var SignedByAgent = class _SignedByAgent {
197
+ nativeAgent;
198
+ relayConnected = false;
199
+ _emailMapping = {};
200
+ constructor(nativeAgent) {
201
+ this.nativeAgent = nativeAgent;
202
+ }
203
+ /**
204
+ * Initialize a new agent or load existing identity.
205
+ *
206
+ * Creates DID keys and stores them securely if this is first run.
207
+ * Loads existing identity if storage already exists.
208
+ *
209
+ * @param storagePath - Directory for agent data (keys, witness cache)
210
+ * @returns SignedByAgent instance
211
+ */
212
+ static async init(storagePath) {
213
+ if (!existsSync(storagePath)) {
214
+ mkdirSync(storagePath, { recursive: true });
215
+ }
216
+ const nativeAgent = await native2.SignedByAgent.init(storagePath);
217
+ return new _SignedByAgent(nativeAgent);
218
+ }
219
+ /**
220
+ * Get the agent's npub (public key in bech32 format).
221
+ */
222
+ get npub() {
223
+ return native2.getAgentNpub(this.nativeAgent);
224
+ }
225
+ /**
226
+ * Set email mapping for enterprises.
227
+ *
228
+ * This tells the agent which email to provide during Gate 1
229
+ * enrollment for each enterprise domain.
230
+ *
231
+ * @param mapping - Dict of enterprise domain -> email address
232
+ */
233
+ setEmailMapping(mapping) {
234
+ this._emailMapping = mapping;
235
+ native2.setEmailMapping(this.nativeAgent, mapping);
236
+ }
237
+ /**
238
+ * Connect to a NOSTR relay.
239
+ *
240
+ * @param relayUrl - WebSocket URL of the relay
241
+ */
242
+ async connectRelay(relayUrl) {
243
+ try {
244
+ await native2.connectRelay(this.nativeAgent, relayUrl);
245
+ this.relayConnected = true;
246
+ } catch (error) {
247
+ throw new RelayConnectionError(`Failed to connect to ${relayUrl}: ${error}`);
248
+ }
249
+ }
250
+ /**
251
+ * Watch for kind 28200 authorization events addressed to this agent.
252
+ *
253
+ * @yields AuthorizationEvent for each incoming authorization request
254
+ */
255
+ async *watchForAuthorizations() {
256
+ if (!this.relayConnected) {
257
+ throw new Error("Not connected to relay. Call connectRelay() first.");
258
+ }
259
+ const eventIterator = native2.subscribeAuthorizations(this.nativeAgent);
260
+ for await (const eventJson of eventIterator) {
261
+ const event = JSON.parse(eventJson);
262
+ yield {
263
+ enterprise: event.enterprise ?? "unknown",
264
+ clientId: event.client_id,
265
+ scopes: event.scopes ?? [],
266
+ eventId: event.id,
267
+ createdAt: event.created_at
268
+ };
269
+ }
270
+ }
271
+ /**
272
+ * Get recent agent activity (kinds 28101, 28102, 28103).
273
+ *
274
+ * @param limit - Maximum number of events to return
275
+ * @returns List of activity events
276
+ */
277
+ getActivityLog(limit = 100) {
278
+ return native2.getActivityLog(this.nativeAgent, limit);
279
+ }
280
+ };
281
+ export {
282
+ ApiError,
283
+ DelegationExpiredError,
284
+ DelegationRevokedError,
285
+ InvalidProofError,
286
+ MerkleRootExpiredError,
287
+ RelayConnectionError,
288
+ ScopeDeniedError,
289
+ SignedByAgent,
290
+ SignedByClient,
291
+ SignedByError
292
+ };
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@signedby/sdk",
3
+ "version": "0.1.0",
4
+ "description": "SignedByMe SDK - Human-controlled identity for autonomous agents",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup src/index.ts --format cjs,esm --dts",
21
+ "test": "vitest",
22
+ "lint": "eslint src/",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "keywords": [
26
+ "signedby",
27
+ "identity",
28
+ "zk-proofs",
29
+ "zero-knowledge",
30
+ "nostr",
31
+ "bitcoin",
32
+ "lightning",
33
+ "authentication",
34
+ "oidc",
35
+ "did"
36
+ ],
37
+ "author": "Privacy Lion <contact@privacy-lion.com>",
38
+ "license": "SSAL-1.0",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/PrivacyLion/SignedByMe.git",
42
+ "directory": "sdk/typescript"
43
+ },
44
+ "homepage": "https://signedbyme.com",
45
+ "bugs": {
46
+ "url": "https://github.com/PrivacyLion/SignedByMe/issues"
47
+ },
48
+ "engines": {
49
+ "node": ">=18.0.0"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^20.0.0",
53
+ "tsup": "^8.0.0",
54
+ "typescript": "^5.0.0",
55
+ "vitest": "^1.0.0",
56
+ "eslint": "^8.0.0",
57
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
58
+ "@typescript-eslint/parser": "^6.0.0"
59
+ },
60
+ "dependencies": {
61
+ "@noble/curves": "^1.3.0",
62
+ "@noble/hashes": "^1.3.0"
63
+ },
64
+ "optionalDependencies": {
65
+ "@signedby/core-linux-x64-gnu": "0.1.0",
66
+ "@signedby/core-linux-arm64-gnu": "0.1.0",
67
+ "@signedby/core-darwin-x64": "0.1.0",
68
+ "@signedby/core-darwin-arm64": "0.1.0",
69
+ "@signedby/core-win32-x64-msvc": "0.1.0"
70
+ }
71
+ }