agents-chain 0.0.2 → 0.0.3
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 +238 -52
- package/dist/app/app-wrapper.d.ts +43 -0
- package/dist/app/app-wrapper.d.ts.map +1 -0
- package/dist/app/app-wrapper.js +122 -0
- package/dist/app/app-wrapper.js.map +1 -0
- package/dist/app/capability-registry.d.ts +31 -0
- package/dist/app/capability-registry.d.ts.map +1 -0
- package/dist/app/capability-registry.js +65 -0
- package/dist/app/capability-registry.js.map +1 -0
- package/dist/audit/audit-exporter.d.ts +82 -0
- package/dist/audit/audit-exporter.d.ts.map +1 -0
- package/dist/audit/audit-exporter.js +94 -0
- package/dist/audit/audit-exporter.js.map +1 -0
- package/dist/audit/audit-log.d.ts +10 -0
- package/dist/audit/audit-log.d.ts.map +1 -1
- package/dist/audit/audit-log.js +18 -0
- package/dist/audit/audit-log.js.map +1 -1
- package/dist/auth/constraints.d.ts +19 -0
- package/dist/auth/constraints.d.ts.map +1 -0
- package/dist/auth/constraints.js +85 -0
- package/dist/auth/constraints.js.map +1 -0
- package/dist/auth/token-verifier.d.ts +26 -2
- package/dist/auth/token-verifier.d.ts.map +1 -1
- package/dist/auth/token-verifier.js +47 -9
- package/dist/auth/token-verifier.js.map +1 -1
- package/dist/chain.d.ts +59 -1
- package/dist/chain.d.ts.map +1 -1
- package/dist/chain.js +115 -0
- package/dist/chain.js.map +1 -1
- package/dist/crypto/ed25519.d.ts.map +1 -1
- package/dist/crypto/ed25519.js +2 -1
- package/dist/crypto/ed25519.js.map +1 -1
- package/dist/crypto/utils.d.ts +1 -1
- package/dist/crypto/utils.d.ts.map +1 -1
- package/dist/host/host-identity.d.ts +66 -0
- package/dist/host/host-identity.d.ts.map +1 -0
- package/dist/host/host-identity.js +109 -0
- package/dist/host/host-identity.js.map +1 -0
- package/dist/index.d.ts +14 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/memory/jti-cache.d.ts +31 -4
- package/dist/memory/jti-cache.d.ts.map +1 -1
- package/dist/memory/jti-cache.js +40 -13
- package/dist/memory/jti-cache.js.map +1 -1
- package/dist/types/capabilities.d.ts +64 -0
- package/dist/types/capabilities.d.ts.map +1 -0
- package/dist/types/capabilities.js +9 -0
- package/dist/types/capabilities.js.map +1 -0
- package/dist/types/chain.d.ts +51 -1
- package/dist/types/chain.d.ts.map +1 -1
- package/dist/types/protocol.d.ts +61 -0
- package/dist/types/protocol.d.ts.map +1 -0
- package/dist/types/protocol.js +10 -0
- package/dist/types/protocol.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
# agents-chain
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**v0.0.3** — A zero-dependency security layer that wraps any app, service object, or AI SDK with Ed25519 identity, JWT-gated capability enforcement, constraint validation, and an encrypted audit trail.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Drop it in front of your billing service, a third-party API client, or an OpenAI/Anthropic SDK — every call is signed, verified, scoped, and logged without touching your existing code.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What it does
|
|
10
|
+
|
|
11
|
+
- **Host + Agent identity** — Ed25519 keypairs with JWK thumbprints as stable IDs. Hosts sign agent registration JWTs; agents sign scoped capability tokens.
|
|
12
|
+
- **9-step JWT verification** — Every capability call mints a fresh 60-second single-use token. Sub, iss, aud, signature, expiry, and JTI replay are all verified before the call proceeds.
|
|
13
|
+
- **Capability registry + app wrapper** — Register named capabilities on any service object. A JavaScript Proxy intercepts method calls by name and gates them through the full auth pipeline.
|
|
14
|
+
- **Constraint enforcement** — Grants can carry `max`, `min`, `in`, `not_in`, or exact-equality constraints on call arguments, enforced before execution.
|
|
15
|
+
- **Encrypted audit log** — AES-256-GCM in-memory log of every call (success, denied, error). Drain to any HTTP endpoint or custom exporter on a schedule or at shutdown.
|
|
16
|
+
- **Adapter interfaces** — Plug in your own Redis client for JTI replay protection across restarts. Plug in your own grant resolver to read active grants from your DB. The package ships no Redis client.
|
|
17
|
+
- **Well-known discovery** — Serve `GET /.well-known/agent-configuration` with one call. Agents discover your capabilities, endpoints, and supported algorithms automatically.
|
|
18
|
+
- **Zero mandatory dependencies** — In-memory defaults for everything. Redis, databases, and HTTP clients are injected by you.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Package overview
|
|
23
|
+
|
|
24
|
+

|
|
25
|
+
|
|
26
|
+
The package has six layers. **HostIdentity** and **AgentIdentity** hold Ed25519 keypairs. **TokenBuilder** mints scoped JWTs; **TokenVerifier** runs the 9-step verification pipeline. **CapabilityRegistry** maps method names to capability definitions; **wrapApp()** turns any object into a secured Proxy using that registry. **AuditLog** records every call into an AES-256-GCM encrypted store and can drain to any **AuditExporter**. All state lives in **EncryptedStore** — there is no network I/O by default.
|
|
11
27
|
|
|
12
28
|
---
|
|
13
29
|
|
|
@@ -23,7 +39,90 @@ pnpm add agents-chain
|
|
|
23
39
|
|
|
24
40
|
---
|
|
25
41
|
|
|
26
|
-
##
|
|
42
|
+
## Wrapping any app — AppChain
|
|
43
|
+
|
|
44
|
+
`AppChain` is the main entry point for wrapping your own services or third-party clients.
|
|
45
|
+
|
|
46
|
+
### Integration flow
|
|
47
|
+
|
|
48
|
+

|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { AppChain, HttpAuditExporter } from 'agents-chain';
|
|
52
|
+
|
|
53
|
+
const chain = await AppChain.create({
|
|
54
|
+
providerName: 'billing-service',
|
|
55
|
+
issuer: 'https://billing.mycompany.com',
|
|
56
|
+
capabilities: [
|
|
57
|
+
{
|
|
58
|
+
name: 'createInvoice',
|
|
59
|
+
description: 'Create a new invoice for a customer',
|
|
60
|
+
inputSchema: {
|
|
61
|
+
type: 'object',
|
|
62
|
+
required: ['customerId', 'amount'],
|
|
63
|
+
properties: {
|
|
64
|
+
customerId: { type: 'string' },
|
|
65
|
+
amount: { type: 'number' },
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
outputSchema: { type: 'object' },
|
|
69
|
+
execute: async (args, ctx) => {
|
|
70
|
+
// ctx carries agentId, hostId, and active permissions
|
|
71
|
+
return billingDb.createInvoice(args.customerId, args.amount);
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
|
|
76
|
+
// Optional: resolve grants from your DB instead of in-memory
|
|
77
|
+
grantResolver: async (agentId, capability) => myDb.getGrant(agentId, capability),
|
|
78
|
+
|
|
79
|
+
// Optional: drain audit log to a hosted endpoint
|
|
80
|
+
auditExporter: new HttpAuditExporter({
|
|
81
|
+
endpoint: 'https://audit.yourservice.com/ingest',
|
|
82
|
+
apiKey: process.env.AUDIT_API_KEY,
|
|
83
|
+
}),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Serve capability discovery
|
|
87
|
+
app.get('/.well-known/agent-configuration', (req, res) =>
|
|
88
|
+
res.json(chain.getWellKnownConfig())
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// Wrap any object — every registered method is now capability-gated
|
|
92
|
+
const secured = chain.wrap(billingService, agentGrants);
|
|
93
|
+
const invoice = await secured.createInvoice({ customerId: 'c1', amount: 500 });
|
|
94
|
+
|
|
95
|
+
// Flush audit log on shutdown
|
|
96
|
+
process.on('SIGTERM', () => chain.drain());
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Per-call security pipeline
|
|
102
|
+
|
|
103
|
+
Every intercepted call goes through this verification pipeline before your code runs.
|
|
104
|
+
|
|
105
|
+

|
|
106
|
+
|
|
107
|
+
| Step | Check | Error on failure |
|
|
108
|
+
|------|-------|-----------------|
|
|
109
|
+
| 1–2 | Decode JWT header + payload, confirm `typ = "agent+jwt"` | `token_invalid` |
|
|
110
|
+
| 3 | `sub` matches registered `agentId` | `agent_not_found` |
|
|
111
|
+
| 4 | `iss` matches registered public key thumbprint | `token_invalid` |
|
|
112
|
+
| 5 | `aud` matches the requested capability name | `capability_denied` |
|
|
113
|
+
| 6 | Ed25519 signature is valid | `token_invalid` |
|
|
114
|
+
| 7 | `exp`/`iat` temporal check + 30s clock skew tolerance | `token_expired` / `token_invalid` |
|
|
115
|
+
| 8 | JTI not seen in 90-second replay window | `token_replayed` |
|
|
116
|
+
| 9 | Agent holds an `active` grant for the capability | `capability_denied` |
|
|
117
|
+
| 9b | Call arguments satisfy all grant constraints | `constraint_violated` |
|
|
118
|
+
|
|
119
|
+
All failures throw `ChainAuthError` and are recorded in the audit log as `result: "denied"`.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Wrapping AI SDKs — AgentsChain
|
|
124
|
+
|
|
125
|
+
For OpenAI and Anthropic clients, use `AgentsChain` instead. It maps SDK method paths to capability strings automatically.
|
|
27
126
|
|
|
28
127
|
### OpenAI
|
|
29
128
|
|
|
@@ -41,10 +140,8 @@ const ai = chain.openai(new OpenAI({ apiKey: process.env.OPENAI_API_KEY }));
|
|
|
41
140
|
|
|
42
141
|
const response = await ai.chat.completions.create({
|
|
43
142
|
model: 'gpt-4o',
|
|
44
|
-
messages: [{ role: 'user', content: 'Summarize the water cycle
|
|
143
|
+
messages: [{ role: 'user', content: 'Summarize the water cycle.' }],
|
|
45
144
|
});
|
|
46
|
-
|
|
47
|
-
console.log(response.choices[0].message.content);
|
|
48
145
|
```
|
|
49
146
|
|
|
50
147
|
### Anthropic
|
|
@@ -64,24 +161,85 @@ const ai = chain.anthropic(new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY
|
|
|
64
161
|
const response = await ai.messages.create({
|
|
65
162
|
model: 'claude-sonnet-4-6',
|
|
66
163
|
max_tokens: 256,
|
|
67
|
-
messages: [{ role: 'user', content: 'Classify
|
|
164
|
+
messages: [{ role: 'user', content: 'Classify: "I love it!"' }],
|
|
68
165
|
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Capability names
|
|
169
|
+
|
|
170
|
+
#### OpenAI
|
|
171
|
+
|
|
172
|
+
| SDK method | Capability string |
|
|
173
|
+
|-----------|------------------|
|
|
174
|
+
| `ai.chat.completions.create()` | `"chat.completion"` |
|
|
175
|
+
| `ai.embeddings.create()` | `"embedding"` |
|
|
176
|
+
| `ai.images.generate()` | `"image.generation"` |
|
|
177
|
+
| `ai.audio.transcriptions.create()` | `"audio.transcription"` |
|
|
178
|
+
| `ai.audio.speech.create()` | `"audio.speech"` |
|
|
179
|
+
| `ai.moderations.create()` | `"moderation"` |
|
|
180
|
+
| `ai.responses.create()` | `"response"` |
|
|
181
|
+
|
|
182
|
+
#### Anthropic
|
|
183
|
+
|
|
184
|
+
| SDK method | Capability string |
|
|
185
|
+
|-----------|------------------|
|
|
186
|
+
| `ai.messages.create()` | `"message"` |
|
|
187
|
+
| `ai.messages.stream()` | `"message.stream"` |
|
|
188
|
+
| `ai.messages.countTokens()` | `"message.count_tokens"` |
|
|
189
|
+
| `ai.completions.create()` | `"completion"` |
|
|
190
|
+
| `ai.beta.messages.create()` | `"message.beta"` |
|
|
191
|
+
|
|
192
|
+
Any method not in these tables passes through without interception.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Grant constraints
|
|
197
|
+
|
|
198
|
+
Constrain what an agent is allowed to pass in call arguments:
|
|
69
199
|
|
|
70
|
-
|
|
200
|
+
```ts
|
|
201
|
+
const grants = [
|
|
202
|
+
{
|
|
203
|
+
capability: 'createInvoice',
|
|
204
|
+
status: 'active',
|
|
205
|
+
constraints: {
|
|
206
|
+
amount: { max: 1000 }, // amount <= 1000
|
|
207
|
+
currency: { in: ['USD', 'EUR'] }, // currency must be one of these
|
|
208
|
+
},
|
|
209
|
+
expiresAt: Date.now() + 86_400_000, // expires in 24h
|
|
210
|
+
},
|
|
211
|
+
];
|
|
212
|
+
|
|
213
|
+
const secured = chain.wrap(billingService, grants);
|
|
214
|
+
|
|
215
|
+
// This passes
|
|
216
|
+
await secured.createInvoice({ customerId: 'c1', amount: 500, currency: 'USD' });
|
|
217
|
+
|
|
218
|
+
// This throws ChainAuthError("constraint_violated")
|
|
219
|
+
await secured.createInvoice({ customerId: 'c1', amount: 2000, currency: 'USD' });
|
|
71
220
|
```
|
|
72
221
|
|
|
222
|
+
Supported operators: `max`, `min`, `in`, `not_in`, exact primitive equality.
|
|
223
|
+
|
|
73
224
|
---
|
|
74
225
|
|
|
75
|
-
##
|
|
226
|
+
## Persistent JTI replay protection
|
|
227
|
+
|
|
228
|
+
By default, JTI replay protection is in-memory and resets on restart. For shared deployments, plug in your own Redis client:
|
|
76
229
|
|
|
77
230
|
```ts
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
231
|
+
import { AppChain } from 'agents-chain';
|
|
232
|
+
|
|
233
|
+
const redisAdapter = {
|
|
234
|
+
has: (key) => redis.exists(key).then(Boolean),
|
|
235
|
+
set: (key, ttlMs) => redis.set(key, '1', 'PX', ttlMs).then(() => {}),
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const chain = await AppChain.create({
|
|
239
|
+
providerName: 'my-service',
|
|
240
|
+
issuer: 'https://myservice.com',
|
|
241
|
+
capabilities: [...],
|
|
242
|
+
jtiAdapter: redisAdapter,
|
|
85
243
|
});
|
|
86
244
|
```
|
|
87
245
|
|
|
@@ -89,67 +247,89 @@ const chain = await AgentsChain.create({
|
|
|
89
247
|
|
|
90
248
|
## Audit log
|
|
91
249
|
|
|
92
|
-
Every
|
|
250
|
+
Every call is recorded in an AES-256-GCM encrypted in-memory log.
|
|
93
251
|
|
|
94
252
|
```ts
|
|
95
253
|
// Get all entries (decrypted)
|
|
96
254
|
const entries = chain.getAuditLog();
|
|
97
255
|
|
|
98
|
-
// Full snapshot with metadata
|
|
99
|
-
const snapshot = chain.exportAudit();
|
|
100
|
-
// { agentId, entries, exportedAt }
|
|
101
|
-
|
|
102
256
|
// Summary counts
|
|
103
257
|
const stats = chain.getStats();
|
|
104
258
|
// { agentId, agentName, hostname, totalCalls, successfulCalls, deniedCalls, errorCalls, registeredAt }
|
|
259
|
+
|
|
260
|
+
// Export and clear — call periodically or on shutdown
|
|
261
|
+
await chain.drain(); // uses auditExporter from config
|
|
262
|
+
await chain.drain(new ConsoleAuditExporter()); // override exporter
|
|
105
263
|
```
|
|
106
264
|
|
|
107
265
|
Each `AuditEntry` contains:
|
|
108
266
|
|
|
109
267
|
| Field | Type | Description |
|
|
110
|
-
|
|
268
|
+
|-------|------|-------------|
|
|
111
269
|
| `id` | `string` | Unique entry ID |
|
|
112
|
-
| `agentId` | `string` |
|
|
113
|
-
| `
|
|
270
|
+
| `agentId` | `string` | Agent that made the call |
|
|
271
|
+
| `agentName` | `string` | Human-readable agent name |
|
|
272
|
+
| `capability` | `string` | Capability requested |
|
|
273
|
+
| `args` | `object` | Sanitized call arguments (secrets redacted) |
|
|
114
274
|
| `result` | `"success" \| "denied" \| "error"` | Outcome |
|
|
275
|
+
| `denialReason` | `string?` | Set when `result === "denied"` |
|
|
276
|
+
| `jti` | `string` | JWT ID used |
|
|
115
277
|
| `timestamp` | `number` | Unix ms |
|
|
116
|
-
| `
|
|
278
|
+
| `durationMs` | `number` | Execution time in ms |
|
|
279
|
+
|
|
280
|
+
Argument keys matching `key`, `secret`, `token`, `password`, `auth`, `credential`, or `bearer` are automatically replaced with `"[REDACTED]"` before logging.
|
|
117
281
|
|
|
118
282
|
---
|
|
119
283
|
|
|
120
|
-
##
|
|
284
|
+
## Host identity
|
|
121
285
|
|
|
122
|
-
`
|
|
286
|
+
`HostIdentity` is the user's anchor for signing agent registration JWTs against an agent-auth server.
|
|
123
287
|
|
|
124
|
-
|
|
288
|
+
```ts
|
|
289
|
+
// chain.host is a HostIdentity instance
|
|
290
|
+
const hostJwt = await chain.host.signJwt();
|
|
291
|
+
const registrationJwt = await chain.host.signAgentRegistrationJwt(agentPublicKeyJwk);
|
|
125
292
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
| `ai.embeddings.create()` | `"embedding"` |
|
|
130
|
-
| `ai.images.generate()` | `"image.generation"` |
|
|
131
|
-
| `ai.audio.transcriptions.create()` | `"audio.transcription"` |
|
|
132
|
-
| `ai.audio.speech.create()` | `"audio.speech"` |
|
|
133
|
-
| `ai.moderations.create()` | `"moderation"` |
|
|
134
|
-
| `ai.responses.create()` | `"response"` |
|
|
293
|
+
// Stable identity across restarts — export and reload the private key
|
|
294
|
+
const privateKeyJwk = await chain.host.exportPrivateKeyJwk();
|
|
295
|
+
// persist privateKeyJwk securely
|
|
135
296
|
|
|
136
|
-
|
|
297
|
+
// On next startup:
|
|
298
|
+
const host = await HostIdentity.fromKeyPair(savedPrivateKeyJwk, savedPublicKeyJwk, config);
|
|
299
|
+
```
|
|
137
300
|
|
|
138
|
-
|
|
139
|
-
|---|---|
|
|
140
|
-
| `ai.messages.create()` | `"message"` |
|
|
141
|
-
| `ai.messages.stream()` | `"message.stream"` |
|
|
142
|
-
| `ai.messages.countTokens()` | `"message.count_tokens"` |
|
|
143
|
-
| `ai.completions.create()` | `"completion"` |
|
|
144
|
-
| `ai.beta.messages.create()` | `"message.beta"` |
|
|
301
|
+
---
|
|
145
302
|
|
|
146
|
-
|
|
303
|
+
## Well-known discovery
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
// Returns AgentConfiguration — serve at GET /.well-known/agent-configuration
|
|
307
|
+
chain.getWellKnownConfig();
|
|
308
|
+
|
|
309
|
+
// {
|
|
310
|
+
// version: "1.0-draft",
|
|
311
|
+
// provider_name: "billing-service",
|
|
312
|
+
// issuer: "https://billing.mycompany.com",
|
|
313
|
+
// algorithms: ["Ed25519"],
|
|
314
|
+
// modes: ["delegated", "autonomous"],
|
|
315
|
+
// approval_methods: ["device_authorization"],
|
|
316
|
+
// endpoints: {
|
|
317
|
+
// register: "/agent/register",
|
|
318
|
+
// capabilities: "/capability/list",
|
|
319
|
+
// execute: "/capability/execute",
|
|
320
|
+
// status: "/agent/status",
|
|
321
|
+
// revoke: "/agent/revoke",
|
|
322
|
+
// ...
|
|
323
|
+
// },
|
|
324
|
+
// default_capabilities: ["createInvoice", ...]
|
|
325
|
+
// }
|
|
326
|
+
```
|
|
147
327
|
|
|
148
328
|
---
|
|
149
329
|
|
|
150
|
-
##
|
|
330
|
+
## Crypto utilities
|
|
151
331
|
|
|
152
|
-
Low-level utilities are exported if you need
|
|
332
|
+
Low-level Ed25519 utilities are exported if you need them directly:
|
|
153
333
|
|
|
154
334
|
```ts
|
|
155
335
|
import {
|
|
@@ -170,6 +350,12 @@ import {
|
|
|
170
350
|
|
|
171
351
|
---
|
|
172
352
|
|
|
353
|
+
## Full architecture
|
|
354
|
+
|
|
355
|
+
See [ARCHITECTURE.md](./ARCHITECTURE.md) for Mermaid diagrams covering the package internals, integration flow, per-call security pipeline, Host JWT flow, well-known discovery, and persistence adapter swap-in points.
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
173
359
|
## License
|
|
174
360
|
|
|
175
361
|
MIT — [brianmwangidev](https://www.npmjs.com/~brianmwangidev)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wrapApp — wraps any object with capability-gated security.
|
|
3
|
+
*
|
|
4
|
+
* This is the generic version of the AI SDK wrappers (openai-wrapper, anthropic-wrapper).
|
|
5
|
+
* Instead of a hardcoded path→capability map, it uses a CapabilityRegistry.
|
|
6
|
+
*
|
|
7
|
+
* For every method call on the wrapped object:
|
|
8
|
+
* 1. Look up capability by method name in the registry
|
|
9
|
+
* 2. If not in registry → call through without any gating (pass-through)
|
|
10
|
+
* 3. If in registry:
|
|
11
|
+
* a. Verify the agent holds an active grant for this capability
|
|
12
|
+
* b. Enforce any constraints on the call arguments
|
|
13
|
+
* c. Call capability.execute(args, agentContext) — NOT the raw target method
|
|
14
|
+
* d. Record in audit log (success / denied / error)
|
|
15
|
+
*
|
|
16
|
+
* Note: The Proxy only intercepts direct method calls (not nested paths).
|
|
17
|
+
* Use the AI SDK wrappers for nested path interception (e.g. client.chat.completions.create).
|
|
18
|
+
* This wrapper is designed for flat service objects where method names are unique.
|
|
19
|
+
*/
|
|
20
|
+
import type { CapabilityRegistry } from "./capability-registry.js";
|
|
21
|
+
import type { AuditLog } from "../audit/audit-log.js";
|
|
22
|
+
import type { TokenBuilder } from "../auth/token-builder.js";
|
|
23
|
+
import type { TokenVerifier } from "../auth/token-verifier.js";
|
|
24
|
+
import type { AgentIdentity } from "../identity/agent-identity.js";
|
|
25
|
+
import type { ResolvedGrant } from "../types/protocol.js";
|
|
26
|
+
export type AppInterceptContext = {
|
|
27
|
+
identity: AgentIdentity;
|
|
28
|
+
builder: TokenBuilder;
|
|
29
|
+
verifier: TokenVerifier;
|
|
30
|
+
log: AuditLog;
|
|
31
|
+
grants: ResolvedGrant[];
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Wrap any object with capability-gated security.
|
|
35
|
+
*
|
|
36
|
+
* @param target The object to wrap (e.g. a service instance)
|
|
37
|
+
* @param registry Capability registry — defines what methods are gated
|
|
38
|
+
* @param ctx Intercept context — identity, auth, audit, grants
|
|
39
|
+
* @returns A Proxy with the same type as target
|
|
40
|
+
*/
|
|
41
|
+
export declare function wrapApp<T extends object>(target: T, registry: CapabilityRegistry, ctx: AppInterceptContext): T;
|
|
42
|
+
export declare function attachRegistry(ctx: AppInterceptContext, registry: CapabilityRegistry): void;
|
|
43
|
+
//# sourceMappingURL=app-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-wrapper.d.ts","sourceRoot":"","sources":["../../src/app/app-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG1D,MAAM,MAAM,mBAAmB,GAAG;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,aAAa,CAAC;IACxB,GAAG,EAAE,QAAQ,CAAC;IACd,MAAM,EAAE,aAAa,EAAE,CAAC;CAC3B,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,EACpC,MAAM,EAAE,CAAC,EACT,QAAQ,EAAE,kBAAkB,EAC5B,GAAG,EAAE,mBAAmB,GACzB,CAAC,CAgBH;AAuFD,wBAAgB,cAAc,CAAC,GAAG,EAAE,mBAAmB,EAAE,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAE3F"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wrapApp — wraps any object with capability-gated security.
|
|
3
|
+
*
|
|
4
|
+
* This is the generic version of the AI SDK wrappers (openai-wrapper, anthropic-wrapper).
|
|
5
|
+
* Instead of a hardcoded path→capability map, it uses a CapabilityRegistry.
|
|
6
|
+
*
|
|
7
|
+
* For every method call on the wrapped object:
|
|
8
|
+
* 1. Look up capability by method name in the registry
|
|
9
|
+
* 2. If not in registry → call through without any gating (pass-through)
|
|
10
|
+
* 3. If in registry:
|
|
11
|
+
* a. Verify the agent holds an active grant for this capability
|
|
12
|
+
* b. Enforce any constraints on the call arguments
|
|
13
|
+
* c. Call capability.execute(args, agentContext) — NOT the raw target method
|
|
14
|
+
* d. Record in audit log (success / denied / error)
|
|
15
|
+
*
|
|
16
|
+
* Note: The Proxy only intercepts direct method calls (not nested paths).
|
|
17
|
+
* Use the AI SDK wrappers for nested path interception (e.g. client.chat.completions.create).
|
|
18
|
+
* This wrapper is designed for flat service objects where method names are unique.
|
|
19
|
+
*/
|
|
20
|
+
import { ChainAuthError } from "../errors/chain-error.js";
|
|
21
|
+
import { enforceConstraints } from "../auth/constraints.js";
|
|
22
|
+
/**
|
|
23
|
+
* Wrap any object with capability-gated security.
|
|
24
|
+
*
|
|
25
|
+
* @param target The object to wrap (e.g. a service instance)
|
|
26
|
+
* @param registry Capability registry — defines what methods are gated
|
|
27
|
+
* @param ctx Intercept context — identity, auth, audit, grants
|
|
28
|
+
* @returns A Proxy with the same type as target
|
|
29
|
+
*/
|
|
30
|
+
export function wrapApp(target, registry, ctx) {
|
|
31
|
+
return new Proxy(target, {
|
|
32
|
+
get(obj, prop) {
|
|
33
|
+
if (typeof prop !== "string")
|
|
34
|
+
return Reflect.get(obj, prop);
|
|
35
|
+
const capability = registry.get(prop);
|
|
36
|
+
const value = Reflect.get(obj, prop);
|
|
37
|
+
// Not a registered capability — pass through without gating
|
|
38
|
+
if (capability === undefined || typeof value !== "function") {
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
return createInterceptedMethod(capability.name, ctx);
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function createInterceptedMethod(capabilityName, ctx) {
|
|
46
|
+
return async (...args) => {
|
|
47
|
+
const callArgs = (args[0] ?? {});
|
|
48
|
+
let jti = "unknown";
|
|
49
|
+
try {
|
|
50
|
+
// Build + verify the single-use JWT
|
|
51
|
+
const { token, claims } = await ctx.builder.build(capabilityName);
|
|
52
|
+
jti = claims.jti;
|
|
53
|
+
const verified = await ctx.verifier.verify(token, capabilityName, ctx.grants);
|
|
54
|
+
// Enforce grant constraints against call arguments
|
|
55
|
+
const grant = ctx.grants.find((g) => g.capability === capabilityName && g.status === "active");
|
|
56
|
+
if (grant?.constraints) {
|
|
57
|
+
enforceConstraints(grant.constraints, callArgs);
|
|
58
|
+
}
|
|
59
|
+
// Build agent context for capability.execute()
|
|
60
|
+
const agentContext = {
|
|
61
|
+
agentId: verified.agentId,
|
|
62
|
+
hostId: verified.hostId ?? "",
|
|
63
|
+
permissions: ctx.grants
|
|
64
|
+
.filter((g) => g.status === "active")
|
|
65
|
+
.map((g) => g.capability),
|
|
66
|
+
};
|
|
67
|
+
// Get the registered capability and execute it
|
|
68
|
+
const registryEntry = getCapabilityFromCtx(capabilityName, ctx);
|
|
69
|
+
if (!registryEntry) {
|
|
70
|
+
throw new ChainAuthError("capability_denied", `Capability "${capabilityName}" not found in registry`);
|
|
71
|
+
}
|
|
72
|
+
const start = Date.now();
|
|
73
|
+
let result;
|
|
74
|
+
try {
|
|
75
|
+
result = await registryEntry.execute(callArgs, agentContext);
|
|
76
|
+
}
|
|
77
|
+
catch (execErr) {
|
|
78
|
+
ctx.log.recordCall({
|
|
79
|
+
context: verified,
|
|
80
|
+
args: callArgs,
|
|
81
|
+
result: "error",
|
|
82
|
+
durationMs: Date.now() - start,
|
|
83
|
+
errorMessage: execErr instanceof Error ? execErr.message : String(execErr),
|
|
84
|
+
});
|
|
85
|
+
throw execErr;
|
|
86
|
+
}
|
|
87
|
+
ctx.log.recordCall({
|
|
88
|
+
context: verified,
|
|
89
|
+
args: callArgs,
|
|
90
|
+
result: "success",
|
|
91
|
+
durationMs: Date.now() - start,
|
|
92
|
+
});
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
if (err instanceof ChainAuthError) {
|
|
97
|
+
ctx.log.recordDenied({
|
|
98
|
+
agentId: ctx.identity.agentId,
|
|
99
|
+
agentName: ctx.identity.registration.agentName,
|
|
100
|
+
hostname: ctx.identity.registration.hostname,
|
|
101
|
+
capability: capabilityName,
|
|
102
|
+
args: callArgs,
|
|
103
|
+
reason: err.message,
|
|
104
|
+
jti,
|
|
105
|
+
});
|
|
106
|
+
throw err;
|
|
107
|
+
}
|
|
108
|
+
throw err;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// Helper — we need registry access at intercept time.
|
|
113
|
+
// We store it on the context via a symbol to keep the type clean.
|
|
114
|
+
const REGISTRY_SYM = Symbol("registry");
|
|
115
|
+
export function attachRegistry(ctx, registry) {
|
|
116
|
+
ctx[REGISTRY_SYM] = registry;
|
|
117
|
+
}
|
|
118
|
+
function getCapabilityFromCtx(name, ctx) {
|
|
119
|
+
const registry = ctx[REGISTRY_SYM];
|
|
120
|
+
return registry?.get(name);
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=app-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-wrapper.js","sourceRoot":"","sources":["../../src/app/app-wrapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CapabilityRegistry — registers Capability objects and generates well-known config.
|
|
3
|
+
*
|
|
4
|
+
* When building an AppChain, you register all capabilities the app exposes.
|
|
5
|
+
* The registry is then used by the app-wrapper Proxy to gate calls and by
|
|
6
|
+
* well-known.ts to generate the discovery config.
|
|
7
|
+
*/
|
|
8
|
+
import type { Capability } from "../types/capabilities.js";
|
|
9
|
+
import type { AgentConfiguration } from "../types/protocol.js";
|
|
10
|
+
export declare class CapabilityRegistry {
|
|
11
|
+
private readonly caps;
|
|
12
|
+
/**
|
|
13
|
+
* Register a capability. Chainable.
|
|
14
|
+
* Throws if a capability with the same name is already registered.
|
|
15
|
+
*/
|
|
16
|
+
register<TIn, TOut>(cap: Capability<TIn, TOut>): this;
|
|
17
|
+
get(name: string): Capability | undefined;
|
|
18
|
+
list(): Capability[];
|
|
19
|
+
has(name: string): boolean;
|
|
20
|
+
get size(): number;
|
|
21
|
+
/**
|
|
22
|
+
* Build an AgentConfiguration object suitable for serving at
|
|
23
|
+
* GET /.well-known/agent-configuration.
|
|
24
|
+
*
|
|
25
|
+
* @param issuer The base URL of the server (e.g. "https://billing.mycompany.com")
|
|
26
|
+
* @param providerName Short name for the app (e.g. "billing-service")
|
|
27
|
+
* @param endpointPrefix Optional prefix for endpoint paths (default: "")
|
|
28
|
+
*/
|
|
29
|
+
buildWellKnownConfig(issuer: string, providerName: string, endpointPrefix?: string): AgentConfiguration;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=capability-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-registry.d.ts","sourceRoot":"","sources":["../../src/app/capability-registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiC;IAEtD;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI;IAQrD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAIzC,IAAI,IAAI,UAAU,EAAE;IAIpB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;;;OAOG;IACH,oBAAoB,CAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,cAAc,SAAK,GACpB,kBAAkB;CAqBxB"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CapabilityRegistry — registers Capability objects and generates well-known config.
|
|
3
|
+
*
|
|
4
|
+
* When building an AppChain, you register all capabilities the app exposes.
|
|
5
|
+
* The registry is then used by the app-wrapper Proxy to gate calls and by
|
|
6
|
+
* well-known.ts to generate the discovery config.
|
|
7
|
+
*/
|
|
8
|
+
export class CapabilityRegistry {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.caps = new Map();
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Register a capability. Chainable.
|
|
14
|
+
* Throws if a capability with the same name is already registered.
|
|
15
|
+
*/
|
|
16
|
+
register(cap) {
|
|
17
|
+
if (this.caps.has(cap.name)) {
|
|
18
|
+
throw new Error(`CapabilityRegistry: capability "${cap.name}" is already registered`);
|
|
19
|
+
}
|
|
20
|
+
this.caps.set(cap.name, cap);
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
get(name) {
|
|
24
|
+
return this.caps.get(name);
|
|
25
|
+
}
|
|
26
|
+
list() {
|
|
27
|
+
return Array.from(this.caps.values());
|
|
28
|
+
}
|
|
29
|
+
has(name) {
|
|
30
|
+
return this.caps.has(name);
|
|
31
|
+
}
|
|
32
|
+
get size() {
|
|
33
|
+
return this.caps.size;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build an AgentConfiguration object suitable for serving at
|
|
37
|
+
* GET /.well-known/agent-configuration.
|
|
38
|
+
*
|
|
39
|
+
* @param issuer The base URL of the server (e.g. "https://billing.mycompany.com")
|
|
40
|
+
* @param providerName Short name for the app (e.g. "billing-service")
|
|
41
|
+
* @param endpointPrefix Optional prefix for endpoint paths (default: "")
|
|
42
|
+
*/
|
|
43
|
+
buildWellKnownConfig(issuer, providerName, endpointPrefix = "") {
|
|
44
|
+
return {
|
|
45
|
+
version: "1.0-draft",
|
|
46
|
+
provider_name: providerName,
|
|
47
|
+
issuer,
|
|
48
|
+
algorithms: ["Ed25519"],
|
|
49
|
+
modes: ["delegated", "autonomous"],
|
|
50
|
+
approval_methods: ["device_authorization"],
|
|
51
|
+
endpoints: {
|
|
52
|
+
register: `${endpointPrefix}/agent/register`,
|
|
53
|
+
capabilities: `${endpointPrefix}/capability/list`,
|
|
54
|
+
execute: `${endpointPrefix}/capability/execute`,
|
|
55
|
+
status: `${endpointPrefix}/agent/status`,
|
|
56
|
+
reactivate: `${endpointPrefix}/agent/reactivate`,
|
|
57
|
+
revoke: `${endpointPrefix}/agent/revoke`,
|
|
58
|
+
rotate_key: `${endpointPrefix}/agent/rotate-key`,
|
|
59
|
+
request_capability: `${endpointPrefix}/agent/request-capability`,
|
|
60
|
+
},
|
|
61
|
+
default_capabilities: Array.from(this.caps.keys()),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=capability-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-registry.js","sourceRoot":"","sources":["../../src/app/capability-registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,OAAO,kBAAkB;IAA/B;QACqB,SAAI,GAAG,IAAI,GAAG,EAAsB,CAAC;IA+D1D,CAAC;IA7DG;;;OAGG;IACH,QAAQ,CAAY,GAA0B;QAC1C,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,mCAAmC,GAAG,CAAC,IAAI,yBAAyB,CAAC,CAAC;QAC1F,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAiB,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,GAAG,CAAC,IAAY;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI;QACA,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,GAAG,CAAC,IAAY;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,IAAI;QACJ,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED;;;;;;;OAOG;IACH,oBAAoB,CAChB,MAAc,EACd,YAAoB,EACpB,cAAc,GAAG,EAAE;QAEnB,OAAO;YACH,OAAO,EAAE,WAAW;YACpB,aAAa,EAAE,YAAY;YAC3B,MAAM;YACN,UAAU,EAAE,CAAC,SAAS,CAAC;YACvB,KAAK,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC;YAClC,gBAAgB,EAAE,CAAC,sBAAsB,CAAC;YAC1C,SAAS,EAAE;gBACP,QAAQ,EAAE,GAAG,cAAc,iBAAiB;gBAC5C,YAAY,EAAE,GAAG,cAAc,kBAAkB;gBACjD,OAAO,EAAE,GAAG,cAAc,qBAAqB;gBAC/C,MAAM,EAAE,GAAG,cAAc,eAAe;gBACxC,UAAU,EAAE,GAAG,cAAc,mBAAmB;gBAChD,MAAM,EAAE,GAAG,cAAc,eAAe;gBACxC,UAAU,EAAE,GAAG,cAAc,mBAAmB;gBAChD,kBAAkB,EAAE,GAAG,cAAc,2BAA2B;aACnE;YACD,oBAAoB,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SACrD,CAAC;IACN,CAAC;CACJ"}
|