@hai.ai/jacs 0.6.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 +237 -0
- package/http.d.ts +13 -0
- package/http.js +154 -0
- package/index.d.ts +178 -0
- package/index.js +343 -0
- package/jacs.darwin-arm64.node +0 -0
- package/jacs.darwin-x64.node +0 -0
- package/jacs.linux-arm-gnueabihf.node +0 -0
- package/jacs.linux-arm-musleabihf.node +0 -0
- package/jacs.linux-arm64-gnu.node +0 -0
- package/jacs.linux-x64-gnu.node +0 -0
- package/jacs.linux-x64-musl.node +0 -0
- package/mcp.d.ts +61 -0
- package/mcp.js +514 -0
- package/mcp.js.map +1 -0
- package/mcp.ts +521 -0
- package/package.json +103 -0
- package/simple.d.ts +573 -0
- package/simple.js +920 -0
- package/src/a2a.d.ts +79 -0
- package/src/a2a.js +617 -0
package/README.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# JACS for Node.js
|
|
2
|
+
|
|
3
|
+
Node.js bindings for JACS (JSON Agent Communication Standard) -- an open data provenance toolkit for signing and verifying AI agent communications. JACS works standalone with no server required; optionally register with [HAI.ai](https://hai.ai) for cross-organization key discovery.
|
|
4
|
+
|
|
5
|
+
**Dependencies**: The `overrides` in `package.json` for `body-parser` and `qs` are for security (CVE-2024-45590). Do not remove them without re-auditing.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @hai.ai/jacs
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The npm package ships prebuilt native bindings for supported targets and does not compile Rust during `npm install`.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
const jacs = require('@hai.ai/jacs/simple');
|
|
19
|
+
|
|
20
|
+
// Load your agent (run `jacs create` first if needed)
|
|
21
|
+
const agent = jacs.load('./jacs.config.json');
|
|
22
|
+
|
|
23
|
+
// Sign a message
|
|
24
|
+
const signed = jacs.signMessage({
|
|
25
|
+
action: 'approve',
|
|
26
|
+
amount: 100
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Verify it
|
|
30
|
+
const result = jacs.verify(signed.raw);
|
|
31
|
+
console.log(`Valid: ${result.valid}`);
|
|
32
|
+
console.log(`Signer: ${result.signerId}`);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Core API
|
|
36
|
+
|
|
37
|
+
| Function | Description |
|
|
38
|
+
|----------|-------------|
|
|
39
|
+
| `create(options)` | Create a new agent programmatically (non-interactive) |
|
|
40
|
+
| `load(configPath)` | Load agent from config file |
|
|
41
|
+
| `verifySelf()` | Verify agent's own integrity |
|
|
42
|
+
| `updateAgent(data)` | Update agent document with new data |
|
|
43
|
+
| `updateDocument(id, data)` | Update existing document with new data |
|
|
44
|
+
| `signMessage(data)` | Sign any JSON data |
|
|
45
|
+
| `signFile(path, embed)` | Sign a file |
|
|
46
|
+
| `verify(doc)` | Verify signed document (JSON string) |
|
|
47
|
+
| `verifyStandalone(doc, opts?)` | Verify without loading an agent (one-off) |
|
|
48
|
+
| `verifyById(id)` | Verify a document by storage ID (`uuid:version`) |
|
|
49
|
+
| `registerWithHai(opts?)` | Register the loaded agent with HAI.ai |
|
|
50
|
+
| `getDnsRecord(domain, ttl?)` | Get DNS TXT record line for the agent |
|
|
51
|
+
| `getWellKnownJson()` | Get well-known JSON for `/.well-known/jacs-pubkey.json` |
|
|
52
|
+
| `reencryptKey(oldPw, newPw)` | Re-encrypt private key with new password |
|
|
53
|
+
| `getPublicKey()` | Get public key for sharing |
|
|
54
|
+
| `isLoaded()` | Check if agent is loaded |
|
|
55
|
+
| `trustAgent(json)` | Add an agent to the local trust store |
|
|
56
|
+
| `listTrustedAgents()` | List all trusted agent IDs |
|
|
57
|
+
| `untrustAgent(id)` | Remove an agent from the trust store |
|
|
58
|
+
| `isTrusted(id)` | Check if an agent is trusted |
|
|
59
|
+
| `getTrustedAgent(id)` | Get a trusted agent's JSON document |
|
|
60
|
+
| `audit(options?)` | Run a read-only security audit; optional `configPath`, `recentN` |
|
|
61
|
+
| `generateVerifyLink(doc, baseUrl?)` | Generate a shareable hai.ai verification URL for a signed document |
|
|
62
|
+
|
|
63
|
+
## Types
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
interface SignedDocument {
|
|
67
|
+
raw: string; // Full JSON document
|
|
68
|
+
documentId: string; // UUID
|
|
69
|
+
agentId: string; // Signer's ID
|
|
70
|
+
timestamp: string; // ISO 8601
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface VerificationResult {
|
|
74
|
+
valid: boolean;
|
|
75
|
+
data?: any;
|
|
76
|
+
signerId: string;
|
|
77
|
+
timestamp: string;
|
|
78
|
+
attachments: Attachment[];
|
|
79
|
+
errors: string[];
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Programmatic Agent Creation
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
const jacs = require('@hai.ai/jacs/simple');
|
|
87
|
+
|
|
88
|
+
const agent = jacs.create({
|
|
89
|
+
name: 'my-agent',
|
|
90
|
+
password: process.env.JACS_PRIVATE_KEY_PASSWORD, // required
|
|
91
|
+
algorithm: 'pq2025', // default; also: "ring-Ed25519", "RSA-PSS"
|
|
92
|
+
dataDirectory: './jacs_data',
|
|
93
|
+
keyDirectory: './jacs_keys',
|
|
94
|
+
});
|
|
95
|
+
console.log(`Created: ${agent.agentId}`);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Verify by Document ID
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
const result = jacs.verifyById('550e8400-e29b-41d4-a716-446655440000:1');
|
|
102
|
+
console.log(`Valid: ${result.valid}`);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Re-encrypt Private Key
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
jacs.reencryptKey('old-password-123!', 'new-Str0ng-P@ss!');
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Password Requirements
|
|
112
|
+
|
|
113
|
+
Passwords must be at least 8 characters and include uppercase, lowercase, a digit, and a special character.
|
|
114
|
+
|
|
115
|
+
### Algorithm Deprecation Notice
|
|
116
|
+
|
|
117
|
+
The `pq-dilithium` algorithm is deprecated. Use `pq2025` (ML-DSA-87, FIPS-204) instead. `pq-dilithium` still works but emits deprecation warnings.
|
|
118
|
+
|
|
119
|
+
## Examples
|
|
120
|
+
|
|
121
|
+
### Sign and Verify
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
const jacs = require('@hai.ai/jacs/simple');
|
|
125
|
+
|
|
126
|
+
jacs.load('./jacs.config.json');
|
|
127
|
+
|
|
128
|
+
// Sign data
|
|
129
|
+
const signed = jacs.signMessage({
|
|
130
|
+
action: 'transfer',
|
|
131
|
+
amount: 500,
|
|
132
|
+
to: 'agent-123'
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Later, verify received data
|
|
136
|
+
const result = jacs.verify(receivedJson);
|
|
137
|
+
if (result.valid) {
|
|
138
|
+
console.log(`Signed by: ${result.signerId}`);
|
|
139
|
+
console.log(`Data: ${JSON.stringify(result.data)}`);
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Update Agent
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
// Get current agent, modify, and update
|
|
147
|
+
const agentDoc = JSON.parse(jacs.exportAgent());
|
|
148
|
+
agentDoc.jacsAgentType = 'updated-service';
|
|
149
|
+
const updated = jacs.updateAgent(agentDoc);
|
|
150
|
+
console.log('Agent updated with new version');
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Update Document
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
// Create a document
|
|
157
|
+
const signed = jacs.signMessage({ status: 'pending', amount: 100 });
|
|
158
|
+
|
|
159
|
+
// Later, update it
|
|
160
|
+
const doc = JSON.parse(signed.raw);
|
|
161
|
+
doc.content.status = 'approved';
|
|
162
|
+
const updated = jacs.updateDocument(signed.documentId, doc);
|
|
163
|
+
console.log('Document updated with new version');
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### File Signing
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
// Reference only (stores hash)
|
|
170
|
+
const signed = jacs.signFile('contract.pdf', false);
|
|
171
|
+
|
|
172
|
+
// Embed content (portable document)
|
|
173
|
+
const embedded = jacs.signFile('contract.pdf', true);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### MCP Integration
|
|
177
|
+
|
|
178
|
+
JACS provides a transport proxy that wraps any MCP transport with automatic signing and verification at the network boundary:
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
import { createJACSTransportProxy } from '@hai.ai/jacs/mcp';
|
|
182
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
183
|
+
|
|
184
|
+
// Wrap any MCP transport with JACS signing
|
|
185
|
+
const baseTransport = new StdioServerTransport();
|
|
186
|
+
const jacsTransport = createJACSTransportProxy(
|
|
187
|
+
baseTransport, './jacs.config.json', 'server'
|
|
188
|
+
);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
See `examples/mcp.simple.server.js` for a complete MCP server example with JACS-signed tools.
|
|
192
|
+
|
|
193
|
+
## HAI Integration
|
|
194
|
+
|
|
195
|
+
The JACS package includes integration with HAI's key distribution service for fetching public keys without requiring local key storage.
|
|
196
|
+
|
|
197
|
+
### Fetch Remote Keys
|
|
198
|
+
|
|
199
|
+
```javascript
|
|
200
|
+
const { fetchRemoteKey } = require('@hai.ai/jacs');
|
|
201
|
+
|
|
202
|
+
// Fetch a public key from HAI's key service
|
|
203
|
+
const keyInfo = fetchRemoteKey('550e8400-e29b-41d4-a716-446655440000', 'latest');
|
|
204
|
+
console.log('Algorithm:', keyInfo.algorithm);
|
|
205
|
+
console.log('Public Key Hash:', keyInfo.publicKeyHash);
|
|
206
|
+
console.log('Agent ID:', keyInfo.agentId);
|
|
207
|
+
console.log('Version:', keyInfo.version);
|
|
208
|
+
|
|
209
|
+
// Use the public key for verification
|
|
210
|
+
const publicKeyBytes = keyInfo.publicKey; // Buffer containing DER-encoded key
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Environment Variables
|
|
214
|
+
|
|
215
|
+
| Variable | Description | Default |
|
|
216
|
+
|----------|-------------|---------|
|
|
217
|
+
| `HAI_KEYS_BASE_URL` | Base URL for the HAI key service | `https://keys.hai.ai` |
|
|
218
|
+
|
|
219
|
+
### HAI Types
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
interface RemotePublicKeyInfo {
|
|
223
|
+
publicKey: Buffer; // DER-encoded public key bytes
|
|
224
|
+
algorithm: string; // e.g., "ed25519", "rsa-pss-sha256"
|
|
225
|
+
publicKeyHash: string; // SHA-256 hash of the public key
|
|
226
|
+
agentId: string; // The agent's unique identifier
|
|
227
|
+
version: string; // The key version
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## See Also
|
|
232
|
+
|
|
233
|
+
- [JACS Book](https://humanassisted.github.io/JACS/) - Full documentation (published book)
|
|
234
|
+
- [Quick Start](https://humanassisted.github.io/JACS/getting-started/quick-start.html)
|
|
235
|
+
- [Source](https://github.com/HumanAssisted/JACS) - GitHub repository
|
|
236
|
+
- [HAI Developer Portal](https://hai.ai/dev)
|
|
237
|
+
- [Examples](./examples/)
|
package/http.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Define JacsOptions if not already defined elsewhere
|
|
2
|
+
interface JacsOptions {
|
|
3
|
+
configPath: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// For Koa
|
|
7
|
+
export function JACSKoaMiddleware(options: JacsOptions): (ctx: any, next: () => Promise<void>) => Promise<void>;
|
|
8
|
+
|
|
9
|
+
// For Express
|
|
10
|
+
export function JACSExpressMiddleware(options: JacsOptions): (req: any, res: any, next: () => Promise<void>) => Promise<void>;
|
|
11
|
+
|
|
12
|
+
// You can keep the old one if it's still used or remove it
|
|
13
|
+
// export function createJacsMiddleware(options?: JacsOptions): (ctx: any, next: () => Promise<void>) => Promise<void>;
|
package/http.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import jacs from './index.js'; // Assuming JACS NAPI is here
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* JACS Middleware for Koa.js applications.
|
|
5
|
+
* Reads the raw request body, verifies JACS, makes payload available as ctx.jacsPayload.
|
|
6
|
+
* Signs the response object from ctx.body before sending.
|
|
7
|
+
* @param {Object} options
|
|
8
|
+
* @param {string} options.configPath - Path to JACS config file for the server.
|
|
9
|
+
*/
|
|
10
|
+
export function JACSKoaMiddleware(options = {}) {
|
|
11
|
+
if (!options.configPath) {
|
|
12
|
+
throw new Error("JACSKoaMiddleware: options.configPath is required.");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return async (ctx, next) => {
|
|
16
|
+
// Ensure JACS NAPI is loaded with the server's config
|
|
17
|
+
// Consider loading this once when the middleware is initialized if jacs.load supports it,
|
|
18
|
+
// or ensure jacs instance is pre-configured. For simplicity, loading per request if not cached.
|
|
19
|
+
try {
|
|
20
|
+
await jacs.load(options.configPath);
|
|
21
|
+
} catch (loadError) {
|
|
22
|
+
console.error("JACSKoaMiddleware: Failed to load JACS config:", loadError);
|
|
23
|
+
ctx.status = 500;
|
|
24
|
+
ctx.body = "JACS configuration error on server.";
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 1. Request Handling
|
|
29
|
+
if (ctx.request.method === 'POST' || ctx.request.method === 'PUT') { // Or any method with a body
|
|
30
|
+
let rawBody = '';
|
|
31
|
+
try {
|
|
32
|
+
const bodyBuffer = [];
|
|
33
|
+
for await (const chunk of ctx.req) { // ctx.req is the Node.js incoming message
|
|
34
|
+
bodyBuffer.push(chunk);
|
|
35
|
+
}
|
|
36
|
+
rawBody = Buffer.concat(bodyBuffer).toString();
|
|
37
|
+
} catch (err) {
|
|
38
|
+
console.error("JACSKoaMiddleware: Error reading raw request body:", err);
|
|
39
|
+
ctx.status = 400;
|
|
40
|
+
ctx.body = 'Failed to read request body.';
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (rawBody) {
|
|
45
|
+
try {
|
|
46
|
+
console.log("JACSKoaMiddleware: Verifying incoming JACS string...");
|
|
47
|
+
const verificationResult = await jacs.verifyResponse(rawBody);
|
|
48
|
+
ctx.state.jacsPayload = verificationResult.payload; // Standard place for Koa state
|
|
49
|
+
ctx.jacsPayload = verificationResult.payload; // For convenience
|
|
50
|
+
console.log("JACSKoaMiddleware: JACS request verified. Payload in ctx.state.jacsPayload / ctx.jacsPayload.");
|
|
51
|
+
} catch (jacsError) {
|
|
52
|
+
console.error("JACSKoaMiddleware: JACS verification failed:", jacsError);
|
|
53
|
+
ctx.status = 400; // Bad Request - JACS validation failed
|
|
54
|
+
ctx.body = `Invalid JACS request: ${jacsError.message}`;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
console.log("JACSKoaMiddleware: No body found in POST/PUT request for JACS verification.");
|
|
59
|
+
// Depending on policy, might error or proceed if JACS is optional for this path
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
await next(); // Call the next middleware (e.g., your route handler)
|
|
64
|
+
|
|
65
|
+
// 2. Response Handling
|
|
66
|
+
// Check if ctx.body is an object intended for signing (and not already a string or buffer)
|
|
67
|
+
if (ctx.body && typeof ctx.body === 'object' && !(ctx.body instanceof String) && !Buffer.isBuffer(ctx.body) && !(typeof ctx.body.pipe === 'function')) {
|
|
68
|
+
try {
|
|
69
|
+
console.log("JACSKoaMiddleware: Signing outgoing response from ctx.body:", ctx.body);
|
|
70
|
+
const jacsStringResponse = await jacs.signRequest(ctx.body);
|
|
71
|
+
ctx.body = jacsStringResponse; // Replace object payload with JACS string
|
|
72
|
+
ctx.type = 'text/plain'; // Set Content-Type for the JACS string
|
|
73
|
+
console.log("JACSKoaMiddleware: JACS response signed.");
|
|
74
|
+
} catch (jacsError) {
|
|
75
|
+
console.error("JACSKoaMiddleware: Failed to sign JACS response:", jacsError);
|
|
76
|
+
// Potentially overwrite ctx.body with an error or re-throw
|
|
77
|
+
ctx.status = 500;
|
|
78
|
+
ctx.body = `Failed to sign JACS response: ${jacsError.message}`;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* JACS Middleware for Express.js applications.
|
|
86
|
+
* Expects raw request body string in req.body (e.g., from express.text()).
|
|
87
|
+
* Verifies JACS, makes payload available as req.jacsPayload.
|
|
88
|
+
* Wraps res.send to sign the response object before sending.
|
|
89
|
+
* @param {Object} options
|
|
90
|
+
* @param {string} options.configPath - Path to JACS config file for the server.
|
|
91
|
+
*/
|
|
92
|
+
export function JACSExpressMiddleware(options = {}) {
|
|
93
|
+
if (!options.configPath) {
|
|
94
|
+
throw new Error("JACSExpressMiddleware: options.configPath is required.");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return async (req, res, next) => {
|
|
98
|
+
// Ensure JACS NAPI is loaded
|
|
99
|
+
try {
|
|
100
|
+
await jacs.load(options.configPath);
|
|
101
|
+
} catch (loadError) {
|
|
102
|
+
console.error("JACSExpressMiddleware: Failed to load JACS config:", loadError);
|
|
103
|
+
res.status(500).send("JACS configuration error on server.");
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 1. Request Handling
|
|
108
|
+
// Assumes prior middleware (like express.text()) has put raw string body into req.body
|
|
109
|
+
if ((req.method === 'POST' || req.method === 'PUT') && typeof req.body === 'string' && req.body.length > 0) {
|
|
110
|
+
try {
|
|
111
|
+
console.log("JACSExpressMiddleware: Verifying incoming JACS string from req.body...");
|
|
112
|
+
const verificationResult = await jacs.verifyResponse(req.body);
|
|
113
|
+
req.jacsPayload = verificationResult.payload;
|
|
114
|
+
console.log("JACSExpressMiddleware: JACS request verified. Payload in req.jacsPayload.");
|
|
115
|
+
} catch (jacsError) {
|
|
116
|
+
console.error("JACSExpressMiddleware: JACS verification failed:", jacsError);
|
|
117
|
+
res.status(400).send(`Invalid JACS request: ${jacsError.message}`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
} else if ((req.method === 'POST' || req.method === 'PUT') && (!req.body || typeof req.body !== 'string')) {
|
|
121
|
+
console.log("JACSExpressMiddleware: req.body is not a JACS string. Ensure express.text() or similar is used before this middleware for POST/PUT.");
|
|
122
|
+
// Depending on policy, you might proceed or error if JACS is mandatory
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 2. Response Handling - Wrap res.send
|
|
126
|
+
const originalSend = res.send.bind(res);
|
|
127
|
+
res.send = async function (body) {
|
|
128
|
+
// 'this' is 'res'
|
|
129
|
+
if (body && typeof body === 'object' && !(body instanceof String) && !Buffer.isBuffer(body) && !(typeof body.pipe === 'function')) {
|
|
130
|
+
try {
|
|
131
|
+
console.log("JACSExpressMiddleware (res.send wrapper): Signing outgoing response object:", body);
|
|
132
|
+
const jacsStringResponse = await jacs.signRequest(body);
|
|
133
|
+
this.type('text/plain'); // Set Content-Type for the JACS string
|
|
134
|
+
console.log("JACSExpressMiddleware (res.send wrapper): JACS response signed.");
|
|
135
|
+
originalSend(jacsStringResponse);
|
|
136
|
+
} catch (jacsError) {
|
|
137
|
+
console.error("JACSExpressMiddleware (res.send wrapper): Failed to sign JACS response:", jacsError);
|
|
138
|
+
// Handle error - send an error response
|
|
139
|
+
if (!this.headersSent) {
|
|
140
|
+
this.status(500).type('text/plain').send(`Failed to sign JACS response: ${jacsError.message}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
// Not an object to sign, or already a string/buffer, send as is
|
|
145
|
+
originalSend(body);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
next(); // Call the next middleware (e.g., your route handler)
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// The old generic middleware, can be removed or kept for other purposes.
|
|
154
|
+
// export function createJacsMiddleware(options = {}) { ... }
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
/** Hash a string using SHA-256. */
|
|
7
|
+
export declare function hashString(data: string): string
|
|
8
|
+
/** Create a JACS configuration object. */
|
|
9
|
+
export declare function createConfig(jacsUseSecurity?: string | undefined | null, jacsDataDirectory?: string | undefined | null, jacsKeyDirectory?: string | undefined | null, jacsAgentPrivateKeyFilename?: string | undefined | null, jacsAgentPublicKeyFilename?: string | undefined | null, jacsAgentKeyAlgorithm?: string | undefined | null, jacsPrivateKeyPassword?: string | undefined | null, jacsAgentIdAndVersion?: string | undefined | null, jacsDefaultStorage?: string | undefined | null): string
|
|
10
|
+
/** Create a JACS agent programmatically (non-interactive). */
|
|
11
|
+
export declare function createAgent(name: string, password: string, algorithm?: string | undefined | null, dataDirectory?: string | undefined | null, keyDirectory?: string | undefined | null, configPath?: string | undefined | null, agentType?: string | undefined | null, description?: string | undefined | null, domain?: string | undefined | null, defaultStorage?: string | undefined | null): string
|
|
12
|
+
/** Add an agent to the local trust store. */
|
|
13
|
+
export declare function trustAgent(agentJson: string): string
|
|
14
|
+
/** List all trusted agent IDs. */
|
|
15
|
+
export declare function listTrustedAgents(): Array<string>
|
|
16
|
+
/** Remove an agent from the trust store. */
|
|
17
|
+
export declare function untrustAgent(agentId: string): void
|
|
18
|
+
/** Check if an agent is in the trust store. */
|
|
19
|
+
export declare function isTrusted(agentId: string): boolean
|
|
20
|
+
/** Get a trusted agent's JSON document. */
|
|
21
|
+
export declare function getTrustedAgent(agentId: string): string
|
|
22
|
+
/**
|
|
23
|
+
* Run a read-only security audit and health checks.
|
|
24
|
+
* Returns the audit result as a JSON string (risks, health_checks, summary).
|
|
25
|
+
*/
|
|
26
|
+
export declare function audit(configPath?: string | undefined | null, recentN?: number | undefined | null): string
|
|
27
|
+
/** @deprecated Use `new JacsAgent()` and `agent.load()` instead. */
|
|
28
|
+
export declare function load(configPath: string): string
|
|
29
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
30
|
+
export declare function signAgent(agentString: string, publicKey: Buffer, publicKeyEncType: string): string
|
|
31
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
32
|
+
export declare function verifyString(data: string, signatureBase64: string, publicKey: Buffer, publicKeyEncType: string): boolean
|
|
33
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
34
|
+
export declare function signString(data: string): string
|
|
35
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
36
|
+
export declare function verifyAgent(agentfile?: string | undefined | null): boolean
|
|
37
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
38
|
+
export declare function updateAgent(newAgentString: string): string
|
|
39
|
+
/** Result of verify_document_standalone. Exposed to JS as { valid, signerId }. */
|
|
40
|
+
export interface VerifyStandaloneResult {
|
|
41
|
+
valid: boolean
|
|
42
|
+
/** Signer agent ID; exposed to JS as signerId (camelCase). */
|
|
43
|
+
signerId: string
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Verify a signed JACS document without loading an agent.
|
|
47
|
+
* Returns { valid, signerId }. Does not use global agent state.
|
|
48
|
+
*/
|
|
49
|
+
export declare function verifyDocumentStandalone(signedDocument: string, keyResolution?: string | undefined | null, dataDirectory?: string | undefined | null, keyDirectory?: string | undefined | null): VerifyStandaloneResult
|
|
50
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
51
|
+
export declare function verifyDocument(documentString: string): boolean
|
|
52
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
53
|
+
export declare function updateDocument(documentKey: string, newDocumentString: string, attachments?: Array<string> | undefined | null, embed?: boolean | undefined | null): string
|
|
54
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
55
|
+
export declare function verifySignature(documentString: string, signatureField?: string | undefined | null): boolean
|
|
56
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
57
|
+
export declare function createAgreement(documentString: string, agentids: Array<string>, question?: string | undefined | null, context?: string | undefined | null, agreementFieldname?: string | undefined | null): string
|
|
58
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
59
|
+
export declare function signAgreement(documentString: string, agreementFieldname?: string | undefined | null): string
|
|
60
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
61
|
+
export declare function createDocument(documentString: string, customSchema?: string | undefined | null, outputfilename?: string | undefined | null, noSave?: boolean | undefined | null, attachments?: string | undefined | null, embed?: boolean | undefined | null): string
|
|
62
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
63
|
+
export declare function checkAgreement(documentString: string, agreementFieldname?: string | undefined | null): string
|
|
64
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
65
|
+
export declare function signRequest(params: any): string
|
|
66
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
67
|
+
export declare function verifyResponse(documentString: string): object
|
|
68
|
+
/** @deprecated Use `new JacsAgent()` and instance methods instead. */
|
|
69
|
+
export declare function verifyResponseWithAgentId(documentString: string): object
|
|
70
|
+
/**
|
|
71
|
+
* Information about a public key fetched from HAI key service.
|
|
72
|
+
*
|
|
73
|
+
* This struct contains the public key data and metadata returned by
|
|
74
|
+
* the HAI key distribution service.
|
|
75
|
+
*/
|
|
76
|
+
export interface RemotePublicKeyInfo {
|
|
77
|
+
/** The raw public key bytes (DER encoded). */
|
|
78
|
+
publicKey: Buffer
|
|
79
|
+
/** The cryptographic algorithm (e.g., "ed25519", "rsa-pss-sha256"). */
|
|
80
|
+
algorithm: string
|
|
81
|
+
/** The hash of the public key (SHA-256). */
|
|
82
|
+
publicKeyHash: string
|
|
83
|
+
/** The agent ID the key belongs to. */
|
|
84
|
+
agentId: string
|
|
85
|
+
/** The version of the key. */
|
|
86
|
+
version: string
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Fetch a public key from HAI's key distribution service.
|
|
90
|
+
*
|
|
91
|
+
* This function retrieves the public key for a specific agent and version
|
|
92
|
+
* from the HAI key distribution service. It is used to obtain trusted public
|
|
93
|
+
* keys for verifying agent signatures without requiring local key storage.
|
|
94
|
+
*
|
|
95
|
+
* # Arguments
|
|
96
|
+
*
|
|
97
|
+
* * `agent_id` - The unique identifier of the agent whose key to fetch.
|
|
98
|
+
* * `version` - The version of the agent's key to fetch. Use "latest" for
|
|
99
|
+
* the most recent version. If not provided, defaults to "latest".
|
|
100
|
+
*
|
|
101
|
+
* # Returns
|
|
102
|
+
*
|
|
103
|
+
* Returns a `RemotePublicKeyInfo` object containing the public key, algorithm, and hash.
|
|
104
|
+
*
|
|
105
|
+
* # Environment Variables
|
|
106
|
+
*
|
|
107
|
+
* * `HAI_KEYS_BASE_URL` - Base URL for the key service. Defaults to `https://keys.hai.ai`.
|
|
108
|
+
*
|
|
109
|
+
* # Example
|
|
110
|
+
*
|
|
111
|
+
* ```javascript
|
|
112
|
+
* const { fetchRemoteKey } = require('@hai.ai/jacs');
|
|
113
|
+
*
|
|
114
|
+
* const keyInfo = fetchRemoteKey('550e8400-e29b-41d4-a716-446655440000', 'latest');
|
|
115
|
+
* console.log('Algorithm:', keyInfo.algorithm);
|
|
116
|
+
* console.log('Hash:', keyInfo.publicKeyHash);
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare function fetchRemoteKey(agentId: string, version?: string | undefined | null): RemotePublicKeyInfo
|
|
120
|
+
/**
|
|
121
|
+
* Build a verification URL for a signed JACS document.
|
|
122
|
+
*
|
|
123
|
+
* Encodes `document` as URL-safe base64 (no padding) and returns a full URL
|
|
124
|
+
* like `https://hai.ai/jacs/verify?s=...`. Throws if the URL would exceed 2048 chars.
|
|
125
|
+
*/
|
|
126
|
+
export declare function generateVerifyLink(document: string, baseUrl: string): string
|
|
127
|
+
/**
|
|
128
|
+
* JacsAgent is a handle to a JACS agent instance.
|
|
129
|
+
* Each instance maintains its own state and can be used independently.
|
|
130
|
+
* This allows multiple agents to be used concurrently in the same process.
|
|
131
|
+
*/
|
|
132
|
+
export declare class JacsAgent {
|
|
133
|
+
/**
|
|
134
|
+
* Create a new empty JacsAgent instance.
|
|
135
|
+
* Call `load()` to initialize it with a configuration.
|
|
136
|
+
*/
|
|
137
|
+
constructor()
|
|
138
|
+
/** Load an agent from a configuration file. */
|
|
139
|
+
load(configPath: string): string
|
|
140
|
+
/** Sign an external agent's document with this agent's registration signature. */
|
|
141
|
+
signAgent(agentString: string, publicKey: Buffer, publicKeyEncType: string): string
|
|
142
|
+
/** Verify a signature on arbitrary string data. */
|
|
143
|
+
verifyString(data: string, signatureBase64: string, publicKey: Buffer, publicKeyEncType: string): boolean
|
|
144
|
+
/** Sign arbitrary string data with this agent's private key. */
|
|
145
|
+
signString(data: string): string
|
|
146
|
+
/** Verify this agent's signature and hash. */
|
|
147
|
+
verifyAgent(agentfile?: string | undefined | null): boolean
|
|
148
|
+
/** Update the agent document with new data. */
|
|
149
|
+
updateAgent(newAgentString: string): string
|
|
150
|
+
/** Verify a document's signature and hash. */
|
|
151
|
+
verifyDocument(documentString: string): boolean
|
|
152
|
+
/** Update an existing document. */
|
|
153
|
+
updateDocument(documentKey: string, newDocumentString: string, attachments?: Array<string> | undefined | null, embed?: boolean | undefined | null): string
|
|
154
|
+
/** Verify a document's signature with an optional custom signature field. */
|
|
155
|
+
verifySignature(documentString: string, signatureField?: string | undefined | null): boolean
|
|
156
|
+
/** Create an agreement on a document. */
|
|
157
|
+
createAgreement(documentString: string, agentids: Array<string>, question?: string | undefined | null, context?: string | undefined | null, agreementFieldname?: string | undefined | null): string
|
|
158
|
+
/** Sign an agreement on a document. */
|
|
159
|
+
signAgreement(documentString: string, agreementFieldname?: string | undefined | null): string
|
|
160
|
+
/** Create a new JACS document. */
|
|
161
|
+
createDocument(documentString: string, customSchema?: string | undefined | null, outputfilename?: string | undefined | null, noSave?: boolean | undefined | null, attachments?: string | undefined | null, embed?: boolean | undefined | null): string
|
|
162
|
+
/** Check an agreement on a document. */
|
|
163
|
+
checkAgreement(documentString: string, agreementFieldname?: string | undefined | null): string
|
|
164
|
+
/**
|
|
165
|
+
* Verify a document looked up by ID from storage.
|
|
166
|
+
*
|
|
167
|
+
* The document_id should be in "uuid:version" format.
|
|
168
|
+
*/
|
|
169
|
+
verifyDocumentById(documentId: string): boolean
|
|
170
|
+
/** Re-encrypt the agent's private key with a new password. */
|
|
171
|
+
reencryptKey(oldPassword: string, newPassword: string): void
|
|
172
|
+
/** Sign a request payload (wraps in a JACS document). */
|
|
173
|
+
signRequest(params: any): string
|
|
174
|
+
/** Verify a response payload. */
|
|
175
|
+
verifyResponse(documentString: string): object
|
|
176
|
+
/** Verify a response payload and return the agent ID. */
|
|
177
|
+
verifyResponseWithAgentId(documentString: string): object
|
|
178
|
+
}
|