notaryos 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # NotaryOS SDK for TypeScript
2
+
3
+ Cryptographic receipts for AI agent actions. Issue, verify, and audit agent behavior with Ed25519 signatures.
4
+
5
+ **Zero dependencies.** Uses native `fetch()` and Web Crypto API. Works in Node 18+, Deno, Bun, and modern browsers.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install notaryos
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ### Issue a Receipt (3 lines)
16
+
17
+ ```typescript
18
+ import { NotaryClient } from 'notaryos';
19
+
20
+ const notary = new NotaryClient({ apiKey: 'notary_live_xxx' });
21
+ const receipt = await notary.issue('data_processing', { key: 'value' });
22
+ console.log(receipt.verify_url); // https://api.agenttownsquare.com/v1/notary/r/abc123
23
+ ```
24
+
25
+ ### Verify a Receipt (no API key needed)
26
+
27
+ ```typescript
28
+ import { verifyReceipt } from 'notaryos';
29
+
30
+ const isValid = await verifyReceipt(receiptJson);
31
+ // true
32
+ ```
33
+
34
+ ### Full Example
35
+
36
+ ```typescript
37
+ import { NotaryClient } from 'notaryos';
38
+
39
+ const notary = new NotaryClient({ apiKey: 'notary_live_xxx' });
40
+
41
+ // Issue a receipt for an agent action
42
+ const receipt = await notary.issue('financial.transfer', {
43
+ from: 'billing-agent',
44
+ to: 'ledger-agent',
45
+ amount: 150.00,
46
+ currency: 'USD',
47
+ });
48
+
49
+ // Verify it
50
+ const result = await notary.verify(receipt);
51
+ console.log(result.valid); // true
52
+ console.log(result.signature_ok); // true
53
+
54
+ // Check service health
55
+ const status = await notary.status();
56
+ console.log(status.status); // "active"
57
+
58
+ // Get public key for offline verification
59
+ const keyInfo = await notary.publicKey();
60
+ console.log(keyInfo.public_key_pem);
61
+ ```
62
+
63
+ ## API Reference
64
+
65
+ ### `NotaryClient`
66
+
67
+ | Method | Auth | Description |
68
+ |--------|------|-------------|
69
+ | `issue(actionType, payload, options?)` | API Key | Issue a signed receipt |
70
+ | `verify(receipt)` | API Key | Verify a receipt |
71
+ | `verifyById(receiptId)` | API Key | Verify by receipt ID |
72
+ | `status()` | API Key | Service health check |
73
+ | `publicKey()` | API Key | Get Ed25519 public key |
74
+ | `me()` | API Key | Authenticated agent info |
75
+
76
+ ### `verifyReceipt(receipt, baseUrl?)`
77
+
78
+ Public verification without API key. Returns `boolean`.
79
+
80
+ ### `computeHash(payload)`
81
+
82
+ SHA-256 hash matching server-side computation. Returns hex string.
83
+
84
+ ## Configuration
85
+
86
+ ```typescript
87
+ const notary = new NotaryClient({
88
+ apiKey: 'notary_live_xxx', // Required
89
+ baseUrl: 'https://...', // Default: https://api.agenttownsquare.com
90
+ timeout: 30_000, // Default: 30s
91
+ maxRetries: 2, // Default: 2
92
+ });
93
+ ```
94
+
95
+ ## Error Handling
96
+
97
+ ```typescript
98
+ import { NotaryClient, AuthenticationError, RateLimitError, ValidationError } from 'notaryos';
99
+
100
+ try {
101
+ const receipt = await notary.issue('action', payload);
102
+ } catch (err) {
103
+ if (err instanceof AuthenticationError) {
104
+ // Invalid API key
105
+ } else if (err instanceof RateLimitError) {
106
+ // Wait err.retryAfter seconds
107
+ } else if (err instanceof ValidationError) {
108
+ // Check err.details
109
+ }
110
+ }
111
+ ```
112
+
113
+ ## Get an API Key
114
+
115
+ 1. Sign up at [notaryos.org](https://notaryos.org)
116
+ 2. Generate an API key from the dashboard
117
+ 3. Keys start with `notary_live_` (production) or `notary_test_` (sandbox)
118
+
119
+ ## Links
120
+
121
+ - [NotaryOS Documentation](https://notaryos.org/docs)
122
+ - [API Reference](https://api.agenttownsquare.com/v1/notary/status)
123
+ - [Public Verification](https://notaryos.org/verify)
124
+
125
+ ## License
126
+
127
+ MIT
@@ -0,0 +1,237 @@
1
+ /**
2
+ * NotaryOS SDK - Cryptographic receipts for AI agent actions.
3
+ *
4
+ * Issue, verify, and audit agent behavior with Ed25519 signatures.
5
+ * Zero dependencies. Uses native fetch() and Web Crypto API.
6
+ *
7
+ * Quick start:
8
+ *
9
+ * import { NotaryClient } from 'notaryos';
10
+ * const notary = new NotaryClient({ apiKey: 'notary_live_xxx' });
11
+ * const receipt = await notary.issue('my_action', { key: 'value' });
12
+ *
13
+ * Verify without API key:
14
+ *
15
+ * import { verifyReceipt } from 'notaryos';
16
+ * const isValid = await verifyReceipt(receiptJson);
17
+ *
18
+ * @packageDocumentation
19
+ */
20
+ declare const SDK_VERSION = "1.0.0";
21
+ /** Client configuration options. */
22
+ interface NotaryConfig {
23
+ /** Your Notary API key (notary_live_xxx or notary_test_xxx). */
24
+ apiKey: string;
25
+ /** API base URL (default: https://api.agenttownsquare.com). */
26
+ baseUrl?: string;
27
+ /** Request timeout in milliseconds (default: 30000). */
28
+ timeout?: number;
29
+ /** Max retry attempts on transient failures (default: 2). */
30
+ maxRetries?: number;
31
+ }
32
+ /** A signed Notary receipt. */
33
+ interface Receipt {
34
+ receipt_id: string;
35
+ timestamp: string;
36
+ agent_id: string;
37
+ action_type: string;
38
+ payload_hash: string;
39
+ signature: string;
40
+ signature_type: string;
41
+ key_id: string;
42
+ kid?: string;
43
+ alg?: string;
44
+ schema_version?: string;
45
+ chain_sequence?: number;
46
+ previous_receipt_hash?: string | null;
47
+ receipt_hash?: string;
48
+ verify_url?: string;
49
+ }
50
+ /** Result of receipt verification. */
51
+ interface VerificationResult {
52
+ valid: boolean;
53
+ signature_ok: boolean;
54
+ structure_ok: boolean;
55
+ chain_ok?: boolean | null;
56
+ reason: string;
57
+ details: Record<string, unknown>;
58
+ from_cache?: boolean;
59
+ }
60
+ /** Notary service status. */
61
+ interface ServiceStatus {
62
+ status: string;
63
+ signature_type: string;
64
+ key_id: string;
65
+ has_public_key: boolean;
66
+ capabilities: string[];
67
+ timestamp: string;
68
+ }
69
+ /** Public key for offline verification. */
70
+ interface PublicKeyInfo {
71
+ key_id: string;
72
+ signature_type: string;
73
+ public_key_pem: string;
74
+ verification_note: string;
75
+ }
76
+ /** Result of a receipt lookup by hash. */
77
+ interface LookupResult {
78
+ found: boolean;
79
+ receipt: Receipt | null;
80
+ verification: VerificationResult | null;
81
+ meta: Record<string, unknown> | null;
82
+ }
83
+ /** Authenticated agent information. */
84
+ interface AgentInfo {
85
+ agent_id: string;
86
+ agent_name: string;
87
+ tier: string;
88
+ scopes: string[];
89
+ rate_limit_per_minute: number;
90
+ }
91
+ /** Options for issuing receipts. */
92
+ interface IssueOptions {
93
+ /** Hash of previous receipt for chaining. */
94
+ previousReceiptHash?: string;
95
+ /** Additional metadata. */
96
+ metadata?: Record<string, unknown>;
97
+ }
98
+ /** Base error for all NotaryOS SDK errors. */
99
+ declare class NotaryError extends Error {
100
+ code: string;
101
+ status: number;
102
+ details: Record<string, unknown>;
103
+ constructor(message: string, code?: string, status?: number, details?: Record<string, unknown>);
104
+ }
105
+ /** Invalid or missing API key. */
106
+ declare class AuthenticationError extends NotaryError {
107
+ constructor(message: string, code?: string);
108
+ }
109
+ /** Rate limit exceeded. */
110
+ declare class RateLimitError extends NotaryError {
111
+ retryAfter?: number;
112
+ constructor(message: string, retryAfter?: number);
113
+ }
114
+ /** Request validation failed. */
115
+ declare class ValidationError extends NotaryError {
116
+ constructor(message: string, details?: Record<string, unknown>);
117
+ }
118
+ /**
119
+ * NotaryOS API client.
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const notary = new NotaryClient({ apiKey: 'notary_live_xxx' });
124
+ *
125
+ * // Issue a receipt
126
+ * const receipt = await notary.issue('data_processing', { key: 'value' });
127
+ *
128
+ * // Verify a receipt
129
+ * const result = await notary.verify(receipt);
130
+ * console.log(result.valid); // true
131
+ *
132
+ * // Check service health
133
+ * const status = await notary.status();
134
+ * ```
135
+ */
136
+ declare class NotaryClient {
137
+ private apiKey;
138
+ private baseUrl;
139
+ private timeout;
140
+ private maxRetries;
141
+ static readonly DEFAULT_BASE_URL = "https://api.agenttownsquare.com";
142
+ static readonly DEFAULT_TIMEOUT = 30000;
143
+ constructor(config: NotaryConfig);
144
+ private request;
145
+ private sleep;
146
+ /**
147
+ * Issue a signed receipt for an action.
148
+ *
149
+ * @param actionType - Type of action (e.g., "data_processing", "api_call")
150
+ * @param payload - Action payload to be receipted
151
+ * @param options - Optional chaining and metadata
152
+ * @returns A signed Receipt
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * const receipt = await notary.issue('transfer', { amount: 100, to: 'agent-b' });
157
+ * console.log(receipt.receipt_id);
158
+ * console.log(receipt.verify_url); // https://...notary/r/abc123
159
+ * ```
160
+ */
161
+ issue(actionType: string, payload: Record<string, unknown>, options?: IssueOptions): Promise<Receipt>;
162
+ /**
163
+ * Verify a receipt's signature and integrity.
164
+ *
165
+ * @param receipt - Receipt object or raw receipt dict
166
+ * @returns VerificationResult with validity details
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * const result = await notary.verify(receipt);
171
+ * if (result.valid) {
172
+ * console.log('Receipt is authentic');
173
+ * }
174
+ * ```
175
+ */
176
+ verify(receipt: Receipt | Record<string, unknown>): Promise<VerificationResult>;
177
+ /** Verify a receipt by its ID (server-side lookup). */
178
+ verifyById(receiptId: string): Promise<VerificationResult>;
179
+ /**
180
+ * Get Notary service status.
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * const status = await notary.status();
185
+ * console.log(status.status); // "active"
186
+ * ```
187
+ */
188
+ status(): Promise<ServiceStatus>;
189
+ /** Get the public key for offline verification. */
190
+ publicKey(): Promise<PublicKeyInfo>;
191
+ /** Get authenticated agent info. */
192
+ me(): Promise<AgentInfo>;
193
+ /**
194
+ * Look up a receipt by hash (public endpoint, no API key required for lookup).
195
+ *
196
+ * @param receiptHash - Full or partial receipt hash (min 16 chars)
197
+ * @returns Lookup result with receipt, verification, and meta
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * const result = await notary.lookup('abc123def456...');
202
+ * if (result.found && result.verification?.valid) {
203
+ * console.log('Receipt is valid!');
204
+ * }
205
+ * ```
206
+ */
207
+ lookup(receiptHash: string): Promise<LookupResult>;
208
+ }
209
+ /**
210
+ * Quick receipt verification without API key.
211
+ *
212
+ * Uses the public /verify endpoint — no authentication needed.
213
+ *
214
+ * @param receipt - Receipt JSON object
215
+ * @param baseUrl - API base URL (default: production)
216
+ * @returns true if the receipt is valid
217
+ *
218
+ * @example
219
+ * ```typescript
220
+ * import { verifyReceipt } from 'notaryos';
221
+ *
222
+ * const isValid = await verifyReceipt(receiptJson);
223
+ * console.log(isValid); // true
224
+ * ```
225
+ */
226
+ declare function verifyReceipt(receipt: Record<string, unknown>, baseUrl?: string): Promise<boolean>;
227
+ /**
228
+ * Compute SHA-256 hash of a payload using Web Crypto API.
229
+ *
230
+ * Matches the server-side hashing for independent verification.
231
+ *
232
+ * @param payload - String or JSON-serializable object
233
+ * @returns Hex-encoded SHA-256 digest
234
+ */
235
+ declare function computeHash(payload: Record<string, unknown> | string): Promise<string>;
236
+
237
+ export { type AgentInfo, AuthenticationError, type IssueOptions, type LookupResult, NotaryClient, type NotaryConfig, NotaryError, type PublicKeyInfo, RateLimitError, type Receipt, SDK_VERSION, type ServiceStatus, ValidationError, type VerificationResult, computeHash, verifyReceipt };
@@ -0,0 +1,237 @@
1
+ /**
2
+ * NotaryOS SDK - Cryptographic receipts for AI agent actions.
3
+ *
4
+ * Issue, verify, and audit agent behavior with Ed25519 signatures.
5
+ * Zero dependencies. Uses native fetch() and Web Crypto API.
6
+ *
7
+ * Quick start:
8
+ *
9
+ * import { NotaryClient } from 'notaryos';
10
+ * const notary = new NotaryClient({ apiKey: 'notary_live_xxx' });
11
+ * const receipt = await notary.issue('my_action', { key: 'value' });
12
+ *
13
+ * Verify without API key:
14
+ *
15
+ * import { verifyReceipt } from 'notaryos';
16
+ * const isValid = await verifyReceipt(receiptJson);
17
+ *
18
+ * @packageDocumentation
19
+ */
20
+ declare const SDK_VERSION = "1.0.0";
21
+ /** Client configuration options. */
22
+ interface NotaryConfig {
23
+ /** Your Notary API key (notary_live_xxx or notary_test_xxx). */
24
+ apiKey: string;
25
+ /** API base URL (default: https://api.agenttownsquare.com). */
26
+ baseUrl?: string;
27
+ /** Request timeout in milliseconds (default: 30000). */
28
+ timeout?: number;
29
+ /** Max retry attempts on transient failures (default: 2). */
30
+ maxRetries?: number;
31
+ }
32
+ /** A signed Notary receipt. */
33
+ interface Receipt {
34
+ receipt_id: string;
35
+ timestamp: string;
36
+ agent_id: string;
37
+ action_type: string;
38
+ payload_hash: string;
39
+ signature: string;
40
+ signature_type: string;
41
+ key_id: string;
42
+ kid?: string;
43
+ alg?: string;
44
+ schema_version?: string;
45
+ chain_sequence?: number;
46
+ previous_receipt_hash?: string | null;
47
+ receipt_hash?: string;
48
+ verify_url?: string;
49
+ }
50
+ /** Result of receipt verification. */
51
+ interface VerificationResult {
52
+ valid: boolean;
53
+ signature_ok: boolean;
54
+ structure_ok: boolean;
55
+ chain_ok?: boolean | null;
56
+ reason: string;
57
+ details: Record<string, unknown>;
58
+ from_cache?: boolean;
59
+ }
60
+ /** Notary service status. */
61
+ interface ServiceStatus {
62
+ status: string;
63
+ signature_type: string;
64
+ key_id: string;
65
+ has_public_key: boolean;
66
+ capabilities: string[];
67
+ timestamp: string;
68
+ }
69
+ /** Public key for offline verification. */
70
+ interface PublicKeyInfo {
71
+ key_id: string;
72
+ signature_type: string;
73
+ public_key_pem: string;
74
+ verification_note: string;
75
+ }
76
+ /** Result of a receipt lookup by hash. */
77
+ interface LookupResult {
78
+ found: boolean;
79
+ receipt: Receipt | null;
80
+ verification: VerificationResult | null;
81
+ meta: Record<string, unknown> | null;
82
+ }
83
+ /** Authenticated agent information. */
84
+ interface AgentInfo {
85
+ agent_id: string;
86
+ agent_name: string;
87
+ tier: string;
88
+ scopes: string[];
89
+ rate_limit_per_minute: number;
90
+ }
91
+ /** Options for issuing receipts. */
92
+ interface IssueOptions {
93
+ /** Hash of previous receipt for chaining. */
94
+ previousReceiptHash?: string;
95
+ /** Additional metadata. */
96
+ metadata?: Record<string, unknown>;
97
+ }
98
+ /** Base error for all NotaryOS SDK errors. */
99
+ declare class NotaryError extends Error {
100
+ code: string;
101
+ status: number;
102
+ details: Record<string, unknown>;
103
+ constructor(message: string, code?: string, status?: number, details?: Record<string, unknown>);
104
+ }
105
+ /** Invalid or missing API key. */
106
+ declare class AuthenticationError extends NotaryError {
107
+ constructor(message: string, code?: string);
108
+ }
109
+ /** Rate limit exceeded. */
110
+ declare class RateLimitError extends NotaryError {
111
+ retryAfter?: number;
112
+ constructor(message: string, retryAfter?: number);
113
+ }
114
+ /** Request validation failed. */
115
+ declare class ValidationError extends NotaryError {
116
+ constructor(message: string, details?: Record<string, unknown>);
117
+ }
118
+ /**
119
+ * NotaryOS API client.
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const notary = new NotaryClient({ apiKey: 'notary_live_xxx' });
124
+ *
125
+ * // Issue a receipt
126
+ * const receipt = await notary.issue('data_processing', { key: 'value' });
127
+ *
128
+ * // Verify a receipt
129
+ * const result = await notary.verify(receipt);
130
+ * console.log(result.valid); // true
131
+ *
132
+ * // Check service health
133
+ * const status = await notary.status();
134
+ * ```
135
+ */
136
+ declare class NotaryClient {
137
+ private apiKey;
138
+ private baseUrl;
139
+ private timeout;
140
+ private maxRetries;
141
+ static readonly DEFAULT_BASE_URL = "https://api.agenttownsquare.com";
142
+ static readonly DEFAULT_TIMEOUT = 30000;
143
+ constructor(config: NotaryConfig);
144
+ private request;
145
+ private sleep;
146
+ /**
147
+ * Issue a signed receipt for an action.
148
+ *
149
+ * @param actionType - Type of action (e.g., "data_processing", "api_call")
150
+ * @param payload - Action payload to be receipted
151
+ * @param options - Optional chaining and metadata
152
+ * @returns A signed Receipt
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * const receipt = await notary.issue('transfer', { amount: 100, to: 'agent-b' });
157
+ * console.log(receipt.receipt_id);
158
+ * console.log(receipt.verify_url); // https://...notary/r/abc123
159
+ * ```
160
+ */
161
+ issue(actionType: string, payload: Record<string, unknown>, options?: IssueOptions): Promise<Receipt>;
162
+ /**
163
+ * Verify a receipt's signature and integrity.
164
+ *
165
+ * @param receipt - Receipt object or raw receipt dict
166
+ * @returns VerificationResult with validity details
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * const result = await notary.verify(receipt);
171
+ * if (result.valid) {
172
+ * console.log('Receipt is authentic');
173
+ * }
174
+ * ```
175
+ */
176
+ verify(receipt: Receipt | Record<string, unknown>): Promise<VerificationResult>;
177
+ /** Verify a receipt by its ID (server-side lookup). */
178
+ verifyById(receiptId: string): Promise<VerificationResult>;
179
+ /**
180
+ * Get Notary service status.
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * const status = await notary.status();
185
+ * console.log(status.status); // "active"
186
+ * ```
187
+ */
188
+ status(): Promise<ServiceStatus>;
189
+ /** Get the public key for offline verification. */
190
+ publicKey(): Promise<PublicKeyInfo>;
191
+ /** Get authenticated agent info. */
192
+ me(): Promise<AgentInfo>;
193
+ /**
194
+ * Look up a receipt by hash (public endpoint, no API key required for lookup).
195
+ *
196
+ * @param receiptHash - Full or partial receipt hash (min 16 chars)
197
+ * @returns Lookup result with receipt, verification, and meta
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * const result = await notary.lookup('abc123def456...');
202
+ * if (result.found && result.verification?.valid) {
203
+ * console.log('Receipt is valid!');
204
+ * }
205
+ * ```
206
+ */
207
+ lookup(receiptHash: string): Promise<LookupResult>;
208
+ }
209
+ /**
210
+ * Quick receipt verification without API key.
211
+ *
212
+ * Uses the public /verify endpoint — no authentication needed.
213
+ *
214
+ * @param receipt - Receipt JSON object
215
+ * @param baseUrl - API base URL (default: production)
216
+ * @returns true if the receipt is valid
217
+ *
218
+ * @example
219
+ * ```typescript
220
+ * import { verifyReceipt } from 'notaryos';
221
+ *
222
+ * const isValid = await verifyReceipt(receiptJson);
223
+ * console.log(isValid); // true
224
+ * ```
225
+ */
226
+ declare function verifyReceipt(receipt: Record<string, unknown>, baseUrl?: string): Promise<boolean>;
227
+ /**
228
+ * Compute SHA-256 hash of a payload using Web Crypto API.
229
+ *
230
+ * Matches the server-side hashing for independent verification.
231
+ *
232
+ * @param payload - String or JSON-serializable object
233
+ * @returns Hex-encoded SHA-256 digest
234
+ */
235
+ declare function computeHash(payload: Record<string, unknown> | string): Promise<string>;
236
+
237
+ export { type AgentInfo, AuthenticationError, type IssueOptions, type LookupResult, NotaryClient, type NotaryConfig, NotaryError, type PublicKeyInfo, RateLimitError, type Receipt, SDK_VERSION, type ServiceStatus, ValidationError, type VerificationResult, computeHash, verifyReceipt };
package/dist/index.js ADDED
@@ -0,0 +1,307 @@
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 __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AuthenticationError: () => AuthenticationError,
24
+ NotaryClient: () => NotaryClient,
25
+ NotaryError: () => NotaryError,
26
+ RateLimitError: () => RateLimitError,
27
+ SDK_VERSION: () => SDK_VERSION,
28
+ ValidationError: () => ValidationError,
29
+ computeHash: () => computeHash,
30
+ verifyReceipt: () => verifyReceipt
31
+ });
32
+ module.exports = __toCommonJS(index_exports);
33
+ var SDK_VERSION = "1.0.0";
34
+ var NotaryError = class extends Error {
35
+ constructor(message, code = "", status = 0, details = {}) {
36
+ super(message);
37
+ this.name = "NotaryError";
38
+ this.code = code;
39
+ this.status = status;
40
+ this.details = details;
41
+ }
42
+ };
43
+ var AuthenticationError = class extends NotaryError {
44
+ constructor(message, code = "ERR_INVALID_API_KEY") {
45
+ super(message, code, 401);
46
+ this.name = "AuthenticationError";
47
+ }
48
+ };
49
+ var RateLimitError = class extends NotaryError {
50
+ constructor(message, retryAfter) {
51
+ super(message, "ERR_RATE_LIMIT_EXCEEDED", 429);
52
+ this.name = "RateLimitError";
53
+ this.retryAfter = retryAfter;
54
+ }
55
+ };
56
+ var ValidationError = class extends NotaryError {
57
+ constructor(message, details = {}) {
58
+ super(message, "ERR_VALIDATION_FAILED", 422, details);
59
+ this.name = "ValidationError";
60
+ }
61
+ };
62
+ var _NotaryClient = class _NotaryClient {
63
+ constructor(config) {
64
+ const { apiKey, baseUrl, timeout, maxRetries } = config;
65
+ if (!apiKey || !(apiKey.startsWith("notary_live_") || apiKey.startsWith("notary_test_"))) {
66
+ throw new AuthenticationError(
67
+ "Invalid API key format. Keys must start with notary_live_ or notary_test_"
68
+ );
69
+ }
70
+ this.apiKey = apiKey;
71
+ this.baseUrl = (baseUrl || _NotaryClient.DEFAULT_BASE_URL).replace(/\/+$/, "");
72
+ this.timeout = timeout || _NotaryClient.DEFAULT_TIMEOUT;
73
+ this.maxRetries = maxRetries ?? 2;
74
+ }
75
+ async request(method, path, body) {
76
+ const url = `${this.baseUrl}/v1/notary${path}`;
77
+ const headers = {
78
+ "X-API-Key": this.apiKey,
79
+ "Content-Type": "application/json",
80
+ "User-Agent": `notary-typescript-sdk/${SDK_VERSION}`
81
+ };
82
+ let lastError = null;
83
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
84
+ const controller = new AbortController();
85
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
86
+ try {
87
+ const response = await fetch(url, {
88
+ method,
89
+ headers,
90
+ body: body ? JSON.stringify(body) : void 0,
91
+ signal: controller.signal
92
+ });
93
+ clearTimeout(timeoutId);
94
+ if (response.ok) {
95
+ const text = await response.text();
96
+ return text ? JSON.parse(text) : {};
97
+ }
98
+ let errorData = {};
99
+ try {
100
+ errorData = await response.json();
101
+ } catch {
102
+ }
103
+ const errorInfo = errorData.error || { message: response.statusText, code: "" };
104
+ const errorMsg = errorInfo.message || response.statusText;
105
+ const errorCode = errorInfo.code || "";
106
+ if (response.status === 401) {
107
+ throw new AuthenticationError(errorMsg, errorCode);
108
+ }
109
+ if (response.status === 429) {
110
+ const retryAfter = parseInt(response.headers.get("Retry-After") || "60", 10);
111
+ if (attempt < this.maxRetries) {
112
+ await this.sleep(Math.min(retryAfter * 1e3, 5e3));
113
+ continue;
114
+ }
115
+ throw new RateLimitError(errorMsg, retryAfter);
116
+ }
117
+ if (response.status === 422) {
118
+ throw new ValidationError(errorMsg, errorInfo.details || {});
119
+ }
120
+ if (response.status >= 500 && attempt < this.maxRetries) {
121
+ await this.sleep(2 ** attempt * 1e3);
122
+ lastError = new NotaryError(errorMsg, errorCode, response.status);
123
+ continue;
124
+ }
125
+ throw new NotaryError(errorMsg, errorCode, response.status, errorInfo.details || {});
126
+ } catch (err) {
127
+ clearTimeout(timeoutId);
128
+ if (err instanceof NotaryError) throw err;
129
+ if (attempt < this.maxRetries) {
130
+ await this.sleep(2 ** attempt * 1e3);
131
+ lastError = err;
132
+ continue;
133
+ }
134
+ throw new NotaryError(
135
+ `Connection failed: ${err.message}`,
136
+ "ERR_CONNECTION"
137
+ );
138
+ }
139
+ }
140
+ throw lastError || new NotaryError("Request failed", "ERR_UNKNOWN");
141
+ }
142
+ sleep(ms) {
143
+ return new Promise((resolve) => setTimeout(resolve, ms));
144
+ }
145
+ /**
146
+ * Issue a signed receipt for an action.
147
+ *
148
+ * @param actionType - Type of action (e.g., "data_processing", "api_call")
149
+ * @param payload - Action payload to be receipted
150
+ * @param options - Optional chaining and metadata
151
+ * @returns A signed Receipt
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * const receipt = await notary.issue('transfer', { amount: 100, to: 'agent-b' });
156
+ * console.log(receipt.receipt_id);
157
+ * console.log(receipt.verify_url); // https://...notary/r/abc123
158
+ * ```
159
+ */
160
+ async issue(actionType, payload, options = {}) {
161
+ const body = {
162
+ action_type: actionType,
163
+ payload
164
+ };
165
+ if (options.previousReceiptHash) {
166
+ body.previous_receipt_hash = options.previousReceiptHash;
167
+ }
168
+ if (options.metadata) {
169
+ body.metadata = options.metadata;
170
+ }
171
+ const response = await this.request("POST", "/issue", body);
172
+ return {
173
+ ...response.receipt,
174
+ receipt_hash: response.receipt_hash,
175
+ verify_url: response.verify_url,
176
+ chain_sequence: response.chain_position
177
+ };
178
+ }
179
+ /**
180
+ * Verify a receipt's signature and integrity.
181
+ *
182
+ * @param receipt - Receipt object or raw receipt dict
183
+ * @returns VerificationResult with validity details
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * const result = await notary.verify(receipt);
188
+ * if (result.valid) {
189
+ * console.log('Receipt is authentic');
190
+ * }
191
+ * ```
192
+ */
193
+ async verify(receipt) {
194
+ return this.request("POST", "/verify", { receipt });
195
+ }
196
+ /** Verify a receipt by its ID (server-side lookup). */
197
+ async verifyById(receiptId) {
198
+ return this.request("POST", "/verify", { receipt_id: receiptId });
199
+ }
200
+ /**
201
+ * Get Notary service status.
202
+ *
203
+ * @example
204
+ * ```typescript
205
+ * const status = await notary.status();
206
+ * console.log(status.status); // "active"
207
+ * ```
208
+ */
209
+ async status() {
210
+ return this.request("GET", "/status");
211
+ }
212
+ /** Get the public key for offline verification. */
213
+ async publicKey() {
214
+ return this.request("GET", "/public-key");
215
+ }
216
+ /** Get authenticated agent info. */
217
+ async me() {
218
+ return this.request("GET", "/agents/me");
219
+ }
220
+ /**
221
+ * Look up a receipt by hash (public endpoint, no API key required for lookup).
222
+ *
223
+ * @param receiptHash - Full or partial receipt hash (min 16 chars)
224
+ * @returns Lookup result with receipt, verification, and meta
225
+ *
226
+ * @example
227
+ * ```typescript
228
+ * const result = await notary.lookup('abc123def456...');
229
+ * if (result.found && result.verification?.valid) {
230
+ * console.log('Receipt is valid!');
231
+ * }
232
+ * ```
233
+ */
234
+ async lookup(receiptHash) {
235
+ const url = `${this.baseUrl}/v1/notary/r/${receiptHash}`;
236
+ const controller = new AbortController();
237
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
238
+ try {
239
+ const response = await fetch(url, {
240
+ method: "GET",
241
+ headers: {
242
+ "Content-Type": "application/json",
243
+ "User-Agent": `notary-typescript-sdk/${SDK_VERSION}`
244
+ },
245
+ signal: controller.signal
246
+ });
247
+ clearTimeout(timeoutId);
248
+ if (response.status === 404) {
249
+ return { found: false, receipt: null, verification: null, meta: null };
250
+ }
251
+ if (!response.ok) {
252
+ throw new NotaryError(
253
+ response.statusText,
254
+ "ERR_LOOKUP",
255
+ response.status
256
+ );
257
+ }
258
+ return await response.json();
259
+ } catch (err) {
260
+ clearTimeout(timeoutId);
261
+ if (err instanceof NotaryError) throw err;
262
+ throw new NotaryError(
263
+ `Connection failed: ${err.message}`,
264
+ "ERR_CONNECTION"
265
+ );
266
+ }
267
+ }
268
+ };
269
+ _NotaryClient.DEFAULT_BASE_URL = "https://api.agenttownsquare.com";
270
+ _NotaryClient.DEFAULT_TIMEOUT = 3e4;
271
+ var NotaryClient = _NotaryClient;
272
+ async function verifyReceipt(receipt, baseUrl = NotaryClient.DEFAULT_BASE_URL) {
273
+ try {
274
+ const response = await fetch(`${baseUrl.replace(/\/+$/, "")}/v1/notary/verify`, {
275
+ method: "POST",
276
+ headers: { "Content-Type": "application/json" },
277
+ body: JSON.stringify({ receipt })
278
+ });
279
+ if (!response.ok) return false;
280
+ const result = await response.json();
281
+ return result.valid === true;
282
+ } catch {
283
+ return false;
284
+ }
285
+ }
286
+ async function computeHash(payload) {
287
+ const data = typeof payload === "string" ? payload : JSON.stringify(payload, Object.keys(payload).sort());
288
+ const encoded = new TextEncoder().encode(data);
289
+ const buffer = await crypto.subtle.digest("SHA-256", encoded);
290
+ const bytes = new Uint8Array(buffer);
291
+ let hex = "";
292
+ for (let i = 0; i < bytes.length; i++) {
293
+ hex += bytes[i].toString(16).padStart(2, "0");
294
+ }
295
+ return hex;
296
+ }
297
+ // Annotate the CommonJS export names for ESM import in node:
298
+ 0 && (module.exports = {
299
+ AuthenticationError,
300
+ NotaryClient,
301
+ NotaryError,
302
+ RateLimitError,
303
+ SDK_VERSION,
304
+ ValidationError,
305
+ computeHash,
306
+ verifyReceipt
307
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,275 @@
1
+ // src/index.ts
2
+ var SDK_VERSION = "1.0.0";
3
+ var NotaryError = class extends Error {
4
+ constructor(message, code = "", status = 0, details = {}) {
5
+ super(message);
6
+ this.name = "NotaryError";
7
+ this.code = code;
8
+ this.status = status;
9
+ this.details = details;
10
+ }
11
+ };
12
+ var AuthenticationError = class extends NotaryError {
13
+ constructor(message, code = "ERR_INVALID_API_KEY") {
14
+ super(message, code, 401);
15
+ this.name = "AuthenticationError";
16
+ }
17
+ };
18
+ var RateLimitError = class extends NotaryError {
19
+ constructor(message, retryAfter) {
20
+ super(message, "ERR_RATE_LIMIT_EXCEEDED", 429);
21
+ this.name = "RateLimitError";
22
+ this.retryAfter = retryAfter;
23
+ }
24
+ };
25
+ var ValidationError = class extends NotaryError {
26
+ constructor(message, details = {}) {
27
+ super(message, "ERR_VALIDATION_FAILED", 422, details);
28
+ this.name = "ValidationError";
29
+ }
30
+ };
31
+ var _NotaryClient = class _NotaryClient {
32
+ constructor(config) {
33
+ const { apiKey, baseUrl, timeout, maxRetries } = config;
34
+ if (!apiKey || !(apiKey.startsWith("notary_live_") || apiKey.startsWith("notary_test_"))) {
35
+ throw new AuthenticationError(
36
+ "Invalid API key format. Keys must start with notary_live_ or notary_test_"
37
+ );
38
+ }
39
+ this.apiKey = apiKey;
40
+ this.baseUrl = (baseUrl || _NotaryClient.DEFAULT_BASE_URL).replace(/\/+$/, "");
41
+ this.timeout = timeout || _NotaryClient.DEFAULT_TIMEOUT;
42
+ this.maxRetries = maxRetries ?? 2;
43
+ }
44
+ async request(method, path, body) {
45
+ const url = `${this.baseUrl}/v1/notary${path}`;
46
+ const headers = {
47
+ "X-API-Key": this.apiKey,
48
+ "Content-Type": "application/json",
49
+ "User-Agent": `notary-typescript-sdk/${SDK_VERSION}`
50
+ };
51
+ let lastError = null;
52
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
53
+ const controller = new AbortController();
54
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
55
+ try {
56
+ const response = await fetch(url, {
57
+ method,
58
+ headers,
59
+ body: body ? JSON.stringify(body) : void 0,
60
+ signal: controller.signal
61
+ });
62
+ clearTimeout(timeoutId);
63
+ if (response.ok) {
64
+ const text = await response.text();
65
+ return text ? JSON.parse(text) : {};
66
+ }
67
+ let errorData = {};
68
+ try {
69
+ errorData = await response.json();
70
+ } catch {
71
+ }
72
+ const errorInfo = errorData.error || { message: response.statusText, code: "" };
73
+ const errorMsg = errorInfo.message || response.statusText;
74
+ const errorCode = errorInfo.code || "";
75
+ if (response.status === 401) {
76
+ throw new AuthenticationError(errorMsg, errorCode);
77
+ }
78
+ if (response.status === 429) {
79
+ const retryAfter = parseInt(response.headers.get("Retry-After") || "60", 10);
80
+ if (attempt < this.maxRetries) {
81
+ await this.sleep(Math.min(retryAfter * 1e3, 5e3));
82
+ continue;
83
+ }
84
+ throw new RateLimitError(errorMsg, retryAfter);
85
+ }
86
+ if (response.status === 422) {
87
+ throw new ValidationError(errorMsg, errorInfo.details || {});
88
+ }
89
+ if (response.status >= 500 && attempt < this.maxRetries) {
90
+ await this.sleep(2 ** attempt * 1e3);
91
+ lastError = new NotaryError(errorMsg, errorCode, response.status);
92
+ continue;
93
+ }
94
+ throw new NotaryError(errorMsg, errorCode, response.status, errorInfo.details || {});
95
+ } catch (err) {
96
+ clearTimeout(timeoutId);
97
+ if (err instanceof NotaryError) throw err;
98
+ if (attempt < this.maxRetries) {
99
+ await this.sleep(2 ** attempt * 1e3);
100
+ lastError = err;
101
+ continue;
102
+ }
103
+ throw new NotaryError(
104
+ `Connection failed: ${err.message}`,
105
+ "ERR_CONNECTION"
106
+ );
107
+ }
108
+ }
109
+ throw lastError || new NotaryError("Request failed", "ERR_UNKNOWN");
110
+ }
111
+ sleep(ms) {
112
+ return new Promise((resolve) => setTimeout(resolve, ms));
113
+ }
114
+ /**
115
+ * Issue a signed receipt for an action.
116
+ *
117
+ * @param actionType - Type of action (e.g., "data_processing", "api_call")
118
+ * @param payload - Action payload to be receipted
119
+ * @param options - Optional chaining and metadata
120
+ * @returns A signed Receipt
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * const receipt = await notary.issue('transfer', { amount: 100, to: 'agent-b' });
125
+ * console.log(receipt.receipt_id);
126
+ * console.log(receipt.verify_url); // https://...notary/r/abc123
127
+ * ```
128
+ */
129
+ async issue(actionType, payload, options = {}) {
130
+ const body = {
131
+ action_type: actionType,
132
+ payload
133
+ };
134
+ if (options.previousReceiptHash) {
135
+ body.previous_receipt_hash = options.previousReceiptHash;
136
+ }
137
+ if (options.metadata) {
138
+ body.metadata = options.metadata;
139
+ }
140
+ const response = await this.request("POST", "/issue", body);
141
+ return {
142
+ ...response.receipt,
143
+ receipt_hash: response.receipt_hash,
144
+ verify_url: response.verify_url,
145
+ chain_sequence: response.chain_position
146
+ };
147
+ }
148
+ /**
149
+ * Verify a receipt's signature and integrity.
150
+ *
151
+ * @param receipt - Receipt object or raw receipt dict
152
+ * @returns VerificationResult with validity details
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * const result = await notary.verify(receipt);
157
+ * if (result.valid) {
158
+ * console.log('Receipt is authentic');
159
+ * }
160
+ * ```
161
+ */
162
+ async verify(receipt) {
163
+ return this.request("POST", "/verify", { receipt });
164
+ }
165
+ /** Verify a receipt by its ID (server-side lookup). */
166
+ async verifyById(receiptId) {
167
+ return this.request("POST", "/verify", { receipt_id: receiptId });
168
+ }
169
+ /**
170
+ * Get Notary service status.
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * const status = await notary.status();
175
+ * console.log(status.status); // "active"
176
+ * ```
177
+ */
178
+ async status() {
179
+ return this.request("GET", "/status");
180
+ }
181
+ /** Get the public key for offline verification. */
182
+ async publicKey() {
183
+ return this.request("GET", "/public-key");
184
+ }
185
+ /** Get authenticated agent info. */
186
+ async me() {
187
+ return this.request("GET", "/agents/me");
188
+ }
189
+ /**
190
+ * Look up a receipt by hash (public endpoint, no API key required for lookup).
191
+ *
192
+ * @param receiptHash - Full or partial receipt hash (min 16 chars)
193
+ * @returns Lookup result with receipt, verification, and meta
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * const result = await notary.lookup('abc123def456...');
198
+ * if (result.found && result.verification?.valid) {
199
+ * console.log('Receipt is valid!');
200
+ * }
201
+ * ```
202
+ */
203
+ async lookup(receiptHash) {
204
+ const url = `${this.baseUrl}/v1/notary/r/${receiptHash}`;
205
+ const controller = new AbortController();
206
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
207
+ try {
208
+ const response = await fetch(url, {
209
+ method: "GET",
210
+ headers: {
211
+ "Content-Type": "application/json",
212
+ "User-Agent": `notary-typescript-sdk/${SDK_VERSION}`
213
+ },
214
+ signal: controller.signal
215
+ });
216
+ clearTimeout(timeoutId);
217
+ if (response.status === 404) {
218
+ return { found: false, receipt: null, verification: null, meta: null };
219
+ }
220
+ if (!response.ok) {
221
+ throw new NotaryError(
222
+ response.statusText,
223
+ "ERR_LOOKUP",
224
+ response.status
225
+ );
226
+ }
227
+ return await response.json();
228
+ } catch (err) {
229
+ clearTimeout(timeoutId);
230
+ if (err instanceof NotaryError) throw err;
231
+ throw new NotaryError(
232
+ `Connection failed: ${err.message}`,
233
+ "ERR_CONNECTION"
234
+ );
235
+ }
236
+ }
237
+ };
238
+ _NotaryClient.DEFAULT_BASE_URL = "https://api.agenttownsquare.com";
239
+ _NotaryClient.DEFAULT_TIMEOUT = 3e4;
240
+ var NotaryClient = _NotaryClient;
241
+ async function verifyReceipt(receipt, baseUrl = NotaryClient.DEFAULT_BASE_URL) {
242
+ try {
243
+ const response = await fetch(`${baseUrl.replace(/\/+$/, "")}/v1/notary/verify`, {
244
+ method: "POST",
245
+ headers: { "Content-Type": "application/json" },
246
+ body: JSON.stringify({ receipt })
247
+ });
248
+ if (!response.ok) return false;
249
+ const result = await response.json();
250
+ return result.valid === true;
251
+ } catch {
252
+ return false;
253
+ }
254
+ }
255
+ async function computeHash(payload) {
256
+ const data = typeof payload === "string" ? payload : JSON.stringify(payload, Object.keys(payload).sort());
257
+ const encoded = new TextEncoder().encode(data);
258
+ const buffer = await crypto.subtle.digest("SHA-256", encoded);
259
+ const bytes = new Uint8Array(buffer);
260
+ let hex = "";
261
+ for (let i = 0; i < bytes.length; i++) {
262
+ hex += bytes[i].toString(16).padStart(2, "0");
263
+ }
264
+ return hex;
265
+ }
266
+ export {
267
+ AuthenticationError,
268
+ NotaryClient,
269
+ NotaryError,
270
+ RateLimitError,
271
+ SDK_VERSION,
272
+ ValidationError,
273
+ computeHash,
274
+ verifyReceipt
275
+ };
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "notaryos",
3
+ "version": "1.0.0",
4
+ "description": "NotaryOS SDK - Cryptographic receipts for AI agent actions. Issue, verify, and audit agent behavior with Ed25519 signatures.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
22
+ "typecheck": "tsc --noEmit",
23
+ "test": "node --test dist/test.js",
24
+ "prepublishOnly": "npm run build"
25
+ },
26
+ "keywords": [
27
+ "notary",
28
+ "cryptographic",
29
+ "receipt",
30
+ "verification",
31
+ "ai",
32
+ "agent",
33
+ "ed25519",
34
+ "audit",
35
+ "accountability",
36
+ "a2a",
37
+ "agent-to-agent"
38
+ ],
39
+ "author": {
40
+ "name": "Agent Town Square",
41
+ "email": "hello@agenttownsquare.com",
42
+ "url": "https://agenttownsquare.com"
43
+ },
44
+ "license": "MIT",
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/hellothere012/notaryos"
48
+ },
49
+ "homepage": "https://notaryos.org",
50
+ "bugs": {
51
+ "url": "https://github.com/hellothere012/notaryos/issues"
52
+ },
53
+ "engines": {
54
+ "node": ">=18.0.0"
55
+ },
56
+ "devDependencies": {
57
+ "tsup": "^8.0.0",
58
+ "typescript": "^5.3.0"
59
+ }
60
+ }