@datacules/agent-identity-fastify 0.2.1

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.
Files changed (2) hide show
  1. package/package.json +24 -0
  2. package/src/index.ts +81 -0
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@datacules/agent-identity-fastify",
3
+ "version": "0.2.1",
4
+ "private": false,
5
+ "description": "Fastify plugin for @datacules/agent-identity",
6
+ "main": "./dist/cjs/index.js",
7
+ "module": "./dist/esm/index.js",
8
+ "types": "./dist/types/index.d.ts",
9
+ "scripts": {
10
+ "build": "tsc -p tsconfig.build.json",
11
+ "type-check": "tsc --noEmit"
12
+ },
13
+ "peerDependencies": {
14
+ "@datacules/agent-identity": "^0.1.0",
15
+ "fastify": ">=4.0.0",
16
+ "fastify-plugin": ">=4.0.0"
17
+ },
18
+ "devDependencies": {
19
+ "@datacules/agent-identity": "*",
20
+ "fastify": "^4",
21
+ "fastify-plugin": "^4",
22
+ "typescript": "^5"
23
+ }
24
+ }
package/src/index.ts ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Fastify plugin for @datacules/agent-identity.
3
+ *
4
+ * Decorates each request with resolvedCredential before the route handler runs.
5
+ *
6
+ * Usage:
7
+ * import Fastify from 'fastify';
8
+ * import { agentIdentityPlugin } from '@datacules/agent-identity-fastify';
9
+ *
10
+ * const app = Fastify();
11
+ * await app.register(agentIdentityPlugin, { credentials, rules, logger });
12
+ *
13
+ * app.post('/ai/complete', async (request, reply) => {
14
+ * const cred = request.resolvedCredential; // typed
15
+ * });
16
+ */
17
+ import fp from 'fastify-plugin';
18
+ import { createRouter } from '@datacules/agent-identity';
19
+ import type {
20
+ AgentRequestContext,
21
+ AuditLogger,
22
+ Credential,
23
+ ResolvedCredential,
24
+ RoutingRule,
25
+ } from '@datacules/agent-identity';
26
+ import type { FastifyPluginAsync, FastifyRequest, FastifyReply } from 'fastify';
27
+
28
+ declare module 'fastify' {
29
+ interface FastifyRequest {
30
+ resolvedCredential: ResolvedCredential | null;
31
+ }
32
+ }
33
+
34
+ export interface AgentIdentityPluginOptions {
35
+ credentials: Credential[];
36
+ rules: RoutingRule[];
37
+ logger?: AuditLogger;
38
+ contextKey?: string;
39
+ passThrough?: boolean;
40
+ }
41
+
42
+ const plugin: FastifyPluginAsync<AgentIdentityPluginOptions> = async (fastify, options) => {
43
+ const {
44
+ credentials,
45
+ rules,
46
+ logger,
47
+ contextKey = 'agentContext',
48
+ passThrough = true,
49
+ } = options;
50
+
51
+ const router = createRouter(credentials, rules, logger);
52
+
53
+ fastify.decorateRequest('resolvedCredential', null);
54
+
55
+ fastify.addHook(
56
+ 'preHandler',
57
+ async (request: FastifyRequest, reply: FastifyReply) => {
58
+ const body = request.body as Record<string, unknown> | null;
59
+ const ctx = body?.[contextKey] as AgentRequestContext | undefined;
60
+
61
+ if (!ctx) {
62
+ if (!passThrough) {
63
+ return reply.status(400).send({ error: `Missing required field: ${contextKey}` });
64
+ }
65
+ return;
66
+ }
67
+
68
+ const resolved = router.resolve(ctx);
69
+ if (!resolved) {
70
+ return reply.status(403).send({ error: 'No credential resolved for this context' });
71
+ }
72
+
73
+ request.resolvedCredential = resolved;
74
+ }
75
+ );
76
+ };
77
+
78
+ export const agentIdentityPlugin = fp(plugin, {
79
+ name: '@datacules/agent-identity-fastify',
80
+ fastify: '>=4.0.0',
81
+ });