@agent-trust/gateway 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 +101 -0
- package/dist/action-registry.d.ts +29 -0
- package/dist/action-registry.d.ts.map +1 -0
- package/dist/action-registry.js +108 -0
- package/dist/action-registry.js.map +1 -0
- package/dist/behavior-tracker.d.ts +78 -0
- package/dist/behavior-tracker.d.ts.map +1 -0
- package/dist/behavior-tracker.js +300 -0
- package/dist/behavior-tracker.js.map +1 -0
- package/dist/gateway.d.ts +59 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +241 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/certificate.d.ts +10 -0
- package/dist/middleware/certificate.d.ts.map +1 -0
- package/dist/middleware/certificate.js +83 -0
- package/dist/middleware/certificate.js.map +1 -0
- package/dist/station-client.d.ts +29 -0
- package/dist/station-client.d.ts.map +1 -0
- package/dist/station-client.js +72 -0
- package/dist/station-client.js.map +1 -0
- package/dist/types.d.ts +183 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { BehaviorTracker } from './behavior-tracker';
|
|
3
|
+
import { GatewayConfig } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* AgentGateway — the core class that website owners instantiate.
|
|
6
|
+
* Creates an Express router with discovery, authentication, action execution,
|
|
7
|
+
* and real-time behavioral tracking.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const gateway = new AgentGateway({ ... });
|
|
11
|
+
* app.use('/agent-gateway', gateway.router());
|
|
12
|
+
*/
|
|
13
|
+
export declare class AgentGateway {
|
|
14
|
+
private stationClient;
|
|
15
|
+
private actionRegistry;
|
|
16
|
+
private behaviorTracker;
|
|
17
|
+
private config;
|
|
18
|
+
constructor(config: GatewayConfig);
|
|
19
|
+
/**
|
|
20
|
+
* Get the behavior tracker instance (for monitoring/dashboard).
|
|
21
|
+
*/
|
|
22
|
+
getBehaviorTracker(): BehaviorTracker;
|
|
23
|
+
/**
|
|
24
|
+
* Create and return the Express router for this gateway.
|
|
25
|
+
* Mount it on any path: app.use('/agent-gateway', gateway.router())
|
|
26
|
+
*/
|
|
27
|
+
router(): Router;
|
|
28
|
+
/**
|
|
29
|
+
* Destroy the gateway and clean up resources.
|
|
30
|
+
*/
|
|
31
|
+
destroy(): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Factory function — creates an AgentGateway instance.
|
|
35
|
+
*
|
|
36
|
+
* Example:
|
|
37
|
+
* const gateway = createGateway({
|
|
38
|
+
* stationUrl: 'https://station.example.com',
|
|
39
|
+
* gatewayId: 'my-site',
|
|
40
|
+
* stationApiKey: 'ats_xxxxx',
|
|
41
|
+
* actions: {
|
|
42
|
+
* 'search': {
|
|
43
|
+
* description: 'Search products',
|
|
44
|
+
* minScore: 30,
|
|
45
|
+
* parameters: { query: { type: 'string', required: true } },
|
|
46
|
+
* handler: async (params) => db.search(params.query)
|
|
47
|
+
* }
|
|
48
|
+
* },
|
|
49
|
+
* behavior: {
|
|
50
|
+
* maxActionsPerMinute: 20, // Stricter rate limit
|
|
51
|
+
* onSuspiciousActivity: (event) => {
|
|
52
|
+
* console.warn('Suspicious agent:', event);
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* });
|
|
56
|
+
* app.use('/agent-gateway', gateway.router());
|
|
57
|
+
*/
|
|
58
|
+
export declare function createGateway(config: GatewayConfig): AgentGateway;
|
|
59
|
+
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EACL,aAAa,EAId,MAAM,SAAS,CAAC;AAEjB;;;;;;;;GAQG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,aAAa;IAWjC;;OAEG;IACH,kBAAkB,IAAI,eAAe;IAIrC;;;OAGG;IACH,MAAM,IAAI,MAAM;IA6MhB;;OAEG;IACH,OAAO,IAAI,IAAI;CAGhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,YAAY,CAEjE"}
|
package/dist/gateway.js
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AgentGateway = void 0;
|
|
4
|
+
exports.createGateway = createGateway;
|
|
5
|
+
const express_1 = require("express");
|
|
6
|
+
const station_client_1 = require("./station-client");
|
|
7
|
+
const action_registry_1 = require("./action-registry");
|
|
8
|
+
const behavior_tracker_1 = require("./behavior-tracker");
|
|
9
|
+
const certificate_1 = require("./middleware/certificate");
|
|
10
|
+
/**
|
|
11
|
+
* AgentGateway — the core class that website owners instantiate.
|
|
12
|
+
* Creates an Express router with discovery, authentication, action execution,
|
|
13
|
+
* and real-time behavioral tracking.
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* const gateway = new AgentGateway({ ... });
|
|
17
|
+
* app.use('/agent-gateway', gateway.router());
|
|
18
|
+
*/
|
|
19
|
+
class AgentGateway {
|
|
20
|
+
constructor(config) {
|
|
21
|
+
this.config = config;
|
|
22
|
+
this.stationClient = new station_client_1.StationClient(config.stationUrl, config.stationApiKey, config.publicKeyRefreshInterval ?? 3600000 // 1 hour default
|
|
23
|
+
);
|
|
24
|
+
this.actionRegistry = new action_registry_1.ActionRegistry(config.actions);
|
|
25
|
+
this.behaviorTracker = new behavior_tracker_1.BehaviorTracker(config.behavior ?? {});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get the behavior tracker instance (for monitoring/dashboard).
|
|
29
|
+
*/
|
|
30
|
+
getBehaviorTracker() {
|
|
31
|
+
return this.behaviorTracker;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create and return the Express router for this gateway.
|
|
35
|
+
* Mount it on any path: app.use('/agent-gateway', gateway.router())
|
|
36
|
+
*/
|
|
37
|
+
router() {
|
|
38
|
+
const router = (0, express_1.Router)();
|
|
39
|
+
// ─── Discovery Endpoints ───
|
|
40
|
+
/**
|
|
41
|
+
* GET /.well-known/agent-gateway
|
|
42
|
+
* Machine-readable manifest of available actions.
|
|
43
|
+
* Agents call this to discover what this gateway offers.
|
|
44
|
+
*/
|
|
45
|
+
router.get('/.well-known/agent-gateway', (_req, res) => {
|
|
46
|
+
const payload = {
|
|
47
|
+
gatewayId: this.config.gatewayId,
|
|
48
|
+
actions: this.actionRegistry.getDiscoveryPayload(),
|
|
49
|
+
certificateIssuer: 'agent-trust-station',
|
|
50
|
+
version: '1.0.0'
|
|
51
|
+
};
|
|
52
|
+
res.json(payload);
|
|
53
|
+
});
|
|
54
|
+
/**
|
|
55
|
+
* GET /actions
|
|
56
|
+
* Alternative discovery endpoint — list available actions.
|
|
57
|
+
*/
|
|
58
|
+
router.get('/actions', (_req, res) => {
|
|
59
|
+
res.json({
|
|
60
|
+
gatewayId: this.config.gatewayId,
|
|
61
|
+
actions: this.actionRegistry.getDiscoveryPayload()
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* GET /behavior/sessions
|
|
66
|
+
* Monitoring endpoint — view active agent sessions and their behavioral scores.
|
|
67
|
+
* Useful for dashboards and real-time monitoring.
|
|
68
|
+
*/
|
|
69
|
+
router.get('/behavior/sessions', (_req, res) => {
|
|
70
|
+
res.json({
|
|
71
|
+
success: true,
|
|
72
|
+
data: {
|
|
73
|
+
activeSessions: this.behaviorTracker.getActiveSessions()
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
// ─── Protected Action Endpoints ───
|
|
78
|
+
// Certificate validation middleware
|
|
79
|
+
const validateCert = (0, certificate_1.createCertificateMiddleware)(this.stationClient);
|
|
80
|
+
/**
|
|
81
|
+
* POST /actions/:actionName
|
|
82
|
+
* Execute an action. Requires a valid agent certificate.
|
|
83
|
+
*
|
|
84
|
+
* Flow:
|
|
85
|
+
* 1. Validate certificate (JWT signature + expiry)
|
|
86
|
+
* 2. Check behavioral score (is agent blocked mid-session?)
|
|
87
|
+
* 3. Check reputation score vs. action minScore
|
|
88
|
+
* 4. Validate parameters
|
|
89
|
+
* 5. Execute handler
|
|
90
|
+
* 6. Record behavior + report to station
|
|
91
|
+
*/
|
|
92
|
+
router.post('/actions/:actionName', validateCert, async (req, res) => {
|
|
93
|
+
const { actionName } = req.params;
|
|
94
|
+
const params = req.body.params || {};
|
|
95
|
+
const certificate = req.agentCertificate;
|
|
96
|
+
// ─── Behavioral Check: Is agent blocked mid-session? ───
|
|
97
|
+
if (this.behaviorTracker.isBlocked(certificate.sub)) {
|
|
98
|
+
const stats = this.behaviorTracker.getStats(certificate.sub);
|
|
99
|
+
res.status(403).json({
|
|
100
|
+
success: false,
|
|
101
|
+
error: 'Agent blocked due to suspicious behavior',
|
|
102
|
+
behaviorScore: 0,
|
|
103
|
+
flags: stats?.flagsTriggered || [],
|
|
104
|
+
hint: 'Your behavioral score dropped too low. Wait for session to expire and improve behavior.'
|
|
105
|
+
});
|
|
106
|
+
// Report the block to station
|
|
107
|
+
this.stationClient.submitReport({
|
|
108
|
+
agentId: certificate.sub,
|
|
109
|
+
gatewayId: this.config.gatewayId,
|
|
110
|
+
certificateJti: certificate.jti,
|
|
111
|
+
actions: [{
|
|
112
|
+
actionType: actionName,
|
|
113
|
+
outcome: 'failure',
|
|
114
|
+
metadata: { reason: 'behavioral_block', params },
|
|
115
|
+
performedAt: new Date().toISOString()
|
|
116
|
+
}]
|
|
117
|
+
}).catch(err => {
|
|
118
|
+
console.error(`[@agent-trust/gateway] Failed to submit report:`, err.message);
|
|
119
|
+
});
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Check if action exists
|
|
123
|
+
const action = this.actionRegistry.getAction(actionName);
|
|
124
|
+
if (!action) {
|
|
125
|
+
// Record the unknown action attempt
|
|
126
|
+
this.behaviorTracker.recordAction(certificate.sub, certificate.agentExternalId, actionName, params, false, false);
|
|
127
|
+
res.status(404).json({
|
|
128
|
+
success: false,
|
|
129
|
+
error: `Action "${actionName}" not found`,
|
|
130
|
+
availableActions: this.actionRegistry.getActionNames()
|
|
131
|
+
});
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// Build agent context from certificate
|
|
135
|
+
const agentContext = {
|
|
136
|
+
agentId: certificate.sub,
|
|
137
|
+
externalId: certificate.agentExternalId,
|
|
138
|
+
developerId: certificate.developerId,
|
|
139
|
+
score: certificate.score,
|
|
140
|
+
identityVerified: certificate.identityVerified
|
|
141
|
+
};
|
|
142
|
+
// Check if score meets threshold BEFORE executing
|
|
143
|
+
const scoreMet = agentContext.score >= action.minScore;
|
|
144
|
+
// Execute the action (actionRegistry handles score check internally)
|
|
145
|
+
const result = await this.actionRegistry.execute(actionName, params, agentContext);
|
|
146
|
+
// ─── Record behavior and analyze ───
|
|
147
|
+
const behavior = this.behaviorTracker.recordAction(certificate.sub, certificate.agentExternalId, actionName, params, result.success, scoreMet);
|
|
148
|
+
// Attach behavioral data to response
|
|
149
|
+
req.behaviorScore = behavior.behaviorScore;
|
|
150
|
+
req.behaviorFlags = behavior.flags;
|
|
151
|
+
// Submit report to station asynchronously (fire-and-forget)
|
|
152
|
+
this.stationClient.submitReport({
|
|
153
|
+
agentId: certificate.sub,
|
|
154
|
+
gatewayId: this.config.gatewayId,
|
|
155
|
+
certificateJti: certificate.jti,
|
|
156
|
+
actions: [{
|
|
157
|
+
actionType: actionName,
|
|
158
|
+
outcome: result.success ? 'success' : 'failure',
|
|
159
|
+
metadata: {
|
|
160
|
+
params,
|
|
161
|
+
behaviorScore: behavior.behaviorScore,
|
|
162
|
+
behaviorFlags: behavior.flags,
|
|
163
|
+
blocked: behavior.blocked
|
|
164
|
+
},
|
|
165
|
+
performedAt: new Date().toISOString()
|
|
166
|
+
}]
|
|
167
|
+
}).catch(err => {
|
|
168
|
+
console.error(`[@agent-trust/gateway] Failed to submit report to station:`, err.message);
|
|
169
|
+
});
|
|
170
|
+
// Return result to the agent
|
|
171
|
+
const response = { ...result };
|
|
172
|
+
// Include behavioral info in response
|
|
173
|
+
if (behavior.flags.length > 0 || behavior.behaviorScore < 80) {
|
|
174
|
+
response.behavior = {
|
|
175
|
+
score: behavior.behaviorScore,
|
|
176
|
+
flags: behavior.flags,
|
|
177
|
+
warning: behavior.behaviorScore < 50
|
|
178
|
+
? 'Your behavioral score is low. Continued suspicious activity will result in blocking.'
|
|
179
|
+
: behavior.flags.length > 0
|
|
180
|
+
? 'Behavioral flags detected. Adjust your interaction pattern.'
|
|
181
|
+
: undefined
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
// If agent was just blocked by this action
|
|
185
|
+
if (behavior.blocked) {
|
|
186
|
+
res.status(403).json({
|
|
187
|
+
success: false,
|
|
188
|
+
error: 'Agent blocked due to suspicious behavior detected during this session',
|
|
189
|
+
behavior: {
|
|
190
|
+
score: behavior.behaviorScore,
|
|
191
|
+
flags: behavior.flags
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (result.success) {
|
|
197
|
+
res.json(response);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
res.status(403).json(response);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
return router;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Destroy the gateway and clean up resources.
|
|
207
|
+
*/
|
|
208
|
+
destroy() {
|
|
209
|
+
this.behaviorTracker.destroy();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
exports.AgentGateway = AgentGateway;
|
|
213
|
+
/**
|
|
214
|
+
* Factory function — creates an AgentGateway instance.
|
|
215
|
+
*
|
|
216
|
+
* Example:
|
|
217
|
+
* const gateway = createGateway({
|
|
218
|
+
* stationUrl: 'https://station.example.com',
|
|
219
|
+
* gatewayId: 'my-site',
|
|
220
|
+
* stationApiKey: 'ats_xxxxx',
|
|
221
|
+
* actions: {
|
|
222
|
+
* 'search': {
|
|
223
|
+
* description: 'Search products',
|
|
224
|
+
* minScore: 30,
|
|
225
|
+
* parameters: { query: { type: 'string', required: true } },
|
|
226
|
+
* handler: async (params) => db.search(params.query)
|
|
227
|
+
* }
|
|
228
|
+
* },
|
|
229
|
+
* behavior: {
|
|
230
|
+
* maxActionsPerMinute: 20, // Stricter rate limit
|
|
231
|
+
* onSuspiciousActivity: (event) => {
|
|
232
|
+
* console.warn('Suspicious agent:', event);
|
|
233
|
+
* }
|
|
234
|
+
* }
|
|
235
|
+
* });
|
|
236
|
+
* app.use('/agent-gateway', gateway.router());
|
|
237
|
+
*/
|
|
238
|
+
function createGateway(config) {
|
|
239
|
+
return new AgentGateway(config);
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { AgentGateway, createGateway } from './gateway';
|
|
2
|
+
export { StationClient } from './station-client';
|
|
3
|
+
export { ActionRegistry } from './action-registry';
|
|
4
|
+
export { BehaviorTracker } from './behavior-tracker';
|
|
5
|
+
export type { GatewayConfig, ActionDefinition, ParameterDefinition, ActionHandler, AgentContext, ActionResult, PublicActionInfo, DiscoveryPayload, GatewayRequest, BehaviorConfig, BehaviorEvent, BehaviorFlag, SessionStats, AgentSession } from './types';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EAEd,cAAc,EACd,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACb,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @agent-trust/gateway — AI Agent Gateway middleware for Express
|
|
3
|
+
//
|
|
4
|
+
// Install on any Express app to let trusted AI agents interact with your site.
|
|
5
|
+
// Agents present cryptographically signed certificates from the Agent Trust Station.
|
|
6
|
+
// The gateway verifies the certificate, checks the agent's reputation score,
|
|
7
|
+
// monitors real-time behavior, and executes the requested action if trusted.
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.BehaviorTracker = exports.ActionRegistry = exports.StationClient = exports.createGateway = exports.AgentGateway = void 0;
|
|
10
|
+
var gateway_1 = require("./gateway");
|
|
11
|
+
Object.defineProperty(exports, "AgentGateway", { enumerable: true, get: function () { return gateway_1.AgentGateway; } });
|
|
12
|
+
Object.defineProperty(exports, "createGateway", { enumerable: true, get: function () { return gateway_1.createGateway; } });
|
|
13
|
+
var station_client_1 = require("./station-client");
|
|
14
|
+
Object.defineProperty(exports, "StationClient", { enumerable: true, get: function () { return station_client_1.StationClient; } });
|
|
15
|
+
var action_registry_1 = require("./action-registry");
|
|
16
|
+
Object.defineProperty(exports, "ActionRegistry", { enumerable: true, get: function () { return action_registry_1.ActionRegistry; } });
|
|
17
|
+
var behavior_tracker_1 = require("./behavior-tracker");
|
|
18
|
+
Object.defineProperty(exports, "BehaviorTracker", { enumerable: true, get: function () { return behavior_tracker_1.BehaviorTracker; } });
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,iEAAiE;AACjE,EAAE;AACF,+EAA+E;AAC/E,qFAAqF;AACrF,6EAA6E;AAC7E,6EAA6E;;;AAE7E,qCAAwD;AAA/C,uGAAA,YAAY,OAAA;AAAE,wGAAA,aAAa,OAAA;AACpC,mDAAiD;AAAxC,+GAAA,aAAa,OAAA;AACtB,qDAAmD;AAA1C,iHAAA,cAAc,OAAA;AACvB,uDAAqD;AAA5C,mHAAA,eAAe,OAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Response, NextFunction } from 'express';
|
|
2
|
+
import { StationClient } from '../station-client';
|
|
3
|
+
import { GatewayRequest } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Create Express middleware that validates agent certificates.
|
|
6
|
+
* Verifies the JWT signature locally using the station's cached public key.
|
|
7
|
+
* Attaches the decoded certificate payload to req.agentCertificate.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createCertificateMiddleware(stationClient: StationClient): (req: GatewayRequest, res: Response, next: NextFunction) => Promise<void>;
|
|
10
|
+
//# sourceMappingURL=certificate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certificate.d.ts","sourceRoot":"","sources":["../../src/middleware/certificate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAsB,cAAc,EAAE,MAAM,UAAU,CAAC;AAsB9D;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,aAAa,IACxD,KAAK,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,mBAyDrE"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createCertificateMiddleware = createCertificateMiddleware;
|
|
7
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
8
|
+
/**
|
|
9
|
+
* Extract the JWT token from the request.
|
|
10
|
+
* Supports Authorization: Bearer header and X-Agent-Certificate header.
|
|
11
|
+
*/
|
|
12
|
+
function extractToken(req) {
|
|
13
|
+
// Check Authorization header
|
|
14
|
+
const authHeader = req.headers.authorization;
|
|
15
|
+
if (authHeader?.startsWith('Bearer ')) {
|
|
16
|
+
return authHeader.slice(7);
|
|
17
|
+
}
|
|
18
|
+
// Check custom header
|
|
19
|
+
const certHeader = req.headers['x-agent-certificate'];
|
|
20
|
+
if (certHeader) {
|
|
21
|
+
return certHeader;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create Express middleware that validates agent certificates.
|
|
27
|
+
* Verifies the JWT signature locally using the station's cached public key.
|
|
28
|
+
* Attaches the decoded certificate payload to req.agentCertificate.
|
|
29
|
+
*/
|
|
30
|
+
function createCertificateMiddleware(stationClient) {
|
|
31
|
+
return async (req, res, next) => {
|
|
32
|
+
const token = extractToken(req);
|
|
33
|
+
if (!token) {
|
|
34
|
+
res.status(401).json({
|
|
35
|
+
success: false,
|
|
36
|
+
error: 'Agent certificate required — pass JWT in Authorization: Bearer header'
|
|
37
|
+
});
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
// Fetch the station's public key (cached)
|
|
42
|
+
const publicKey = await stationClient.getPublicKey();
|
|
43
|
+
// Verify the JWT locally
|
|
44
|
+
const payload = jsonwebtoken_1.default.verify(token, publicKey, {
|
|
45
|
+
algorithms: ['RS256'],
|
|
46
|
+
issuer: 'agent-trust-station'
|
|
47
|
+
});
|
|
48
|
+
// Check agent status
|
|
49
|
+
if (payload.status === 'banned' || payload.status === 'suspended') {
|
|
50
|
+
res.status(403).json({
|
|
51
|
+
success: false,
|
|
52
|
+
error: `Agent is ${payload.status}`
|
|
53
|
+
});
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Attach to request
|
|
57
|
+
req.agentCertificate = payload;
|
|
58
|
+
req.agentToken = token;
|
|
59
|
+
next();
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error instanceof jsonwebtoken_1.default.TokenExpiredError) {
|
|
63
|
+
res.status(401).json({
|
|
64
|
+
success: false,
|
|
65
|
+
error: 'Certificate expired — request a new one from the station'
|
|
66
|
+
});
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (error instanceof jsonwebtoken_1.default.JsonWebTokenError) {
|
|
70
|
+
res.status(401).json({
|
|
71
|
+
success: false,
|
|
72
|
+
error: 'Invalid certificate — signature verification failed'
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
res.status(500).json({
|
|
77
|
+
success: false,
|
|
78
|
+
error: 'Certificate validation failed'
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=certificate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certificate.js","sourceRoot":"","sources":["../../src/middleware/certificate.ts"],"names":[],"mappings":";;;;;AA8BA,kEA0DC;AAvFD,gEAA+B;AAI/B;;;GAGG;AACH,SAAS,YAAY,CAAC,GAAmB;IACvC,6BAA6B;IAC7B,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IAC7C,IAAI,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,sBAAsB;IACtB,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,qBAAqB,CAAuB,CAAC;IAC5E,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAgB,2BAA2B,CAAC,aAA4B;IACtE,OAAO,KAAK,EAAE,GAAmB,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACtE,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAEhC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,uEAAuE;aAC/E,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,0CAA0C;YAC1C,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,YAAY,EAAE,CAAC;YAErD,yBAAyB;YACzB,MAAM,OAAO,GAAG,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE;gBAC3C,UAAU,EAAE,CAAC,OAAO,CAAC;gBACrB,MAAM,EAAE,qBAAqB;aAC9B,CAAuB,CAAC;YAEzB,qBAAqB;YACrB,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBAClE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,YAAY,OAAO,CAAC,MAAM,EAAE;iBACpC,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,oBAAoB;YACpB,GAAG,CAAC,gBAAgB,GAAG,OAAO,CAAC;YAC/B,GAAG,CAAC,UAAU,GAAG,KAAK,CAAC;YACvB,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,sBAAG,CAAC,iBAAiB,EAAE,CAAC;gBAC3C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,0DAA0D;iBAClE,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,IAAI,KAAK,YAAY,sBAAG,CAAC,iBAAiB,EAAE,CAAC;gBAC3C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,qDAAqD;iBAC7D,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,+BAA+B;aACvC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { GatewayReportPayload } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* HTTP client for communicating with the Agent Trust Station.
|
|
4
|
+
* Handles public key caching and report submission.
|
|
5
|
+
*/
|
|
6
|
+
export declare class StationClient {
|
|
7
|
+
private stationUrl;
|
|
8
|
+
private apiKey;
|
|
9
|
+
private cachedPublicKey;
|
|
10
|
+
private publicKeyFetchedAt;
|
|
11
|
+
private refreshInterval;
|
|
12
|
+
constructor(stationUrl: string, apiKey: string, refreshInterval: number);
|
|
13
|
+
/**
|
|
14
|
+
* Fetch the station's public key (PEM format).
|
|
15
|
+
* Caches the key and only refreshes after the refresh interval expires.
|
|
16
|
+
*/
|
|
17
|
+
getPublicKey(): Promise<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Submit a behavior report to the station.
|
|
20
|
+
* Called after an agent performs actions through the gateway.
|
|
21
|
+
*/
|
|
22
|
+
submitReport(report: GatewayReportPayload): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Verify a certificate remotely via the station (fallback).
|
|
25
|
+
* Prefer local verification using the public key for speed.
|
|
26
|
+
*/
|
|
27
|
+
verifyRemote(token: string): Promise<Record<string, unknown> | null>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=station-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"station-client.d.ts","sourceRoot":"","sources":["../src/station-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE/C;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,eAAe,CAAS;gBAEpB,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM;IAOvE;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IA6BrC;;;OAGG;IACG,YAAY,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB/D;;;OAGG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAY3E"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StationClient = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* HTTP client for communicating with the Agent Trust Station.
|
|
6
|
+
* Handles public key caching and report submission.
|
|
7
|
+
*/
|
|
8
|
+
class StationClient {
|
|
9
|
+
constructor(stationUrl, apiKey, refreshInterval) {
|
|
10
|
+
this.cachedPublicKey = null;
|
|
11
|
+
this.publicKeyFetchedAt = 0;
|
|
12
|
+
// Strip trailing slash
|
|
13
|
+
this.stationUrl = stationUrl.replace(/\/+$/, '');
|
|
14
|
+
this.apiKey = apiKey;
|
|
15
|
+
this.refreshInterval = refreshInterval;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Fetch the station's public key (PEM format).
|
|
19
|
+
* Caches the key and only refreshes after the refresh interval expires.
|
|
20
|
+
*/
|
|
21
|
+
async getPublicKey() {
|
|
22
|
+
const now = Date.now();
|
|
23
|
+
// Return cached key if still fresh
|
|
24
|
+
if (this.cachedPublicKey && (now - this.publicKeyFetchedAt) < this.refreshInterval) {
|
|
25
|
+
return this.cachedPublicKey;
|
|
26
|
+
}
|
|
27
|
+
// Fetch from station
|
|
28
|
+
const response = await fetch(`${this.stationUrl}/.well-known/station-keys`);
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
throw new Error(`Failed to fetch station public key: ${response.status} ${response.statusText}`);
|
|
31
|
+
}
|
|
32
|
+
const data = await response.json();
|
|
33
|
+
if (!data.pem) {
|
|
34
|
+
throw new Error('Station response missing PEM public key');
|
|
35
|
+
}
|
|
36
|
+
this.cachedPublicKey = data.pem;
|
|
37
|
+
this.publicKeyFetchedAt = now;
|
|
38
|
+
return this.cachedPublicKey;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Submit a behavior report to the station.
|
|
42
|
+
* Called after an agent performs actions through the gateway.
|
|
43
|
+
*/
|
|
44
|
+
async submitReport(report) {
|
|
45
|
+
const response = await fetch(`${this.stationUrl}/reports`, {
|
|
46
|
+
method: 'POST',
|
|
47
|
+
headers: {
|
|
48
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
49
|
+
'Content-Type': 'application/json'
|
|
50
|
+
},
|
|
51
|
+
body: JSON.stringify(report)
|
|
52
|
+
});
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
const errorBody = await response.text().catch(() => 'Unknown error');
|
|
55
|
+
throw new Error(`Failed to submit report to station: ${response.status} — ${errorBody}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Verify a certificate remotely via the station (fallback).
|
|
60
|
+
* Prefer local verification using the public key for speed.
|
|
61
|
+
*/
|
|
62
|
+
async verifyRemote(token) {
|
|
63
|
+
const response = await fetch(`${this.stationUrl}/certificates/verify?token=${encodeURIComponent(token)}`);
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const data = await response.json();
|
|
68
|
+
return data.data?.valid ? data.data.payload ?? null : null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.StationClient = StationClient;
|
|
72
|
+
//# sourceMappingURL=station-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"station-client.js","sourceRoot":"","sources":["../src/station-client.ts"],"names":[],"mappings":";;;AAEA;;;GAGG;AACH,MAAa,aAAa;IAOxB,YAAY,UAAkB,EAAE,MAAc,EAAE,eAAuB;QAJ/D,oBAAe,GAAkB,IAAI,CAAC;QACtC,uBAAkB,GAAW,CAAC,CAAC;QAIrC,uBAAuB;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;IACzC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,mCAAmC;QACnC,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YACnF,OAAO,IAAI,CAAC,eAAe,CAAC;QAC9B,CAAC;QAED,qBAAqB;QACrB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,UAAU,2BAA2B,CAAC,CAAC;QAE5E,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,uCAAuC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAChF,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAsB,CAAC;QAEvD,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC;QAChC,IAAI,CAAC,kBAAkB,GAAG,GAAG,CAAC;QAE9B,OAAO,IAAI,CAAC,eAAgB,CAAC;IAC/B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,MAA4B;QAC7C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,UAAU,UAAU,EAAE;YACzD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACxC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC7B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC;YACrE,MAAM,IAAI,KAAK,CAAC,uCAAuC,QAAQ,CAAC,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,KAAa;QAC9B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,GAAG,IAAI,CAAC,UAAU,8BAA8B,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAC5E,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAuE,CAAC;QACxG,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7D,CAAC;CACF;AAnFD,sCAmFC"}
|