@dirxai/core 0.3.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.
@@ -0,0 +1,34 @@
1
+ // src/auth/context.ts
2
+ var AgentContext = class {
3
+ sub;
4
+ svc;
5
+ roles;
6
+ orgId;
7
+ teamId;
8
+ raw;
9
+ constructor(payload) {
10
+ this.sub = payload.sub;
11
+ this.svc = payload.svc ?? "unknown";
12
+ this.roles = Object.freeze(payload.roles ?? []);
13
+ this.orgId = payload.org_id;
14
+ this.teamId = payload.team_id;
15
+ this.raw = payload;
16
+ }
17
+ hasRole(role) {
18
+ return this.roles.includes(role);
19
+ }
20
+ isAgent() {
21
+ return this.hasRole("agent");
22
+ }
23
+ isAdmin() {
24
+ return this.hasRole("admin");
25
+ }
26
+ /** Token expiry as Date, or null if no exp claim. */
27
+ get expiresAt() {
28
+ return this.raw.exp ? new Date(this.raw.exp * 1e3) : null;
29
+ }
30
+ };
31
+
32
+ export {
33
+ AgentContext
34
+ };
@@ -0,0 +1,59 @@
1
+ import { JWTPayload } from 'jose';
2
+
3
+ /**
4
+ * JWKS client — fetches and caches the DirX gateway's public key set.
5
+ *
6
+ * Uses the `jose` library for JWK parsing and JWT verification.
7
+ * Keys are cached in memory with a configurable TTL (default 5 min).
8
+ */
9
+
10
+ interface JwksClientOptions {
11
+ /** JWKS endpoint URL. Default: https://api.dirx.ai/.well-known/jwks.json */
12
+ jwksUrl?: string;
13
+ /** Expected JWT issuer. Default: https://api.dirx.ai */
14
+ issuer?: string;
15
+ /** Expected JWT audience. Default: dirx */
16
+ audience?: string;
17
+ }
18
+ interface DirxTokenPayload extends JWTPayload {
19
+ sub: string;
20
+ svc?: string;
21
+ roles?: string[];
22
+ org_id?: string;
23
+ team_id?: string;
24
+ }
25
+ declare class JwksClient {
26
+ private readonly jwks;
27
+ private readonly issuer;
28
+ private readonly audience;
29
+ constructor(options?: JwksClientOptions);
30
+ /**
31
+ * Verify a JWT token against the JWKS endpoint.
32
+ * Returns the decoded payload on success, throws DirxError on failure.
33
+ */
34
+ verify(token: string): Promise<DirxTokenPayload>;
35
+ }
36
+
37
+ /**
38
+ * AgentContext — request-scoped context extracted from a verified JWT.
39
+ *
40
+ * Provides typed access to the agent identity, roles, and org/team scope.
41
+ * Created by the Guard middleware and attached to the request.
42
+ */
43
+
44
+ declare class AgentContext {
45
+ readonly sub: string;
46
+ readonly svc: string;
47
+ readonly roles: readonly string[];
48
+ readonly orgId: string | undefined;
49
+ readonly teamId: string | undefined;
50
+ readonly raw: DirxTokenPayload;
51
+ constructor(payload: DirxTokenPayload);
52
+ hasRole(role: string): boolean;
53
+ isAgent(): boolean;
54
+ isAdmin(): boolean;
55
+ /** Token expiry as Date, or null if no exp claim. */
56
+ get expiresAt(): Date | null;
57
+ }
58
+
59
+ export { AgentContext as A, type DirxTokenPayload as D, type JwksClientOptions as J, JwksClient as a };
@@ -0,0 +1,59 @@
1
+ import { JWTPayload } from 'jose';
2
+
3
+ /**
4
+ * JWKS client — fetches and caches the DirX gateway's public key set.
5
+ *
6
+ * Uses the `jose` library for JWK parsing and JWT verification.
7
+ * Keys are cached in memory with a configurable TTL (default 5 min).
8
+ */
9
+
10
+ interface JwksClientOptions {
11
+ /** JWKS endpoint URL. Default: https://api.dirx.ai/.well-known/jwks.json */
12
+ jwksUrl?: string;
13
+ /** Expected JWT issuer. Default: https://api.dirx.ai */
14
+ issuer?: string;
15
+ /** Expected JWT audience. Default: dirx */
16
+ audience?: string;
17
+ }
18
+ interface DirxTokenPayload extends JWTPayload {
19
+ sub: string;
20
+ svc?: string;
21
+ roles?: string[];
22
+ org_id?: string;
23
+ team_id?: string;
24
+ }
25
+ declare class JwksClient {
26
+ private readonly jwks;
27
+ private readonly issuer;
28
+ private readonly audience;
29
+ constructor(options?: JwksClientOptions);
30
+ /**
31
+ * Verify a JWT token against the JWKS endpoint.
32
+ * Returns the decoded payload on success, throws DirxError on failure.
33
+ */
34
+ verify(token: string): Promise<DirxTokenPayload>;
35
+ }
36
+
37
+ /**
38
+ * AgentContext — request-scoped context extracted from a verified JWT.
39
+ *
40
+ * Provides typed access to the agent identity, roles, and org/team scope.
41
+ * Created by the Guard middleware and attached to the request.
42
+ */
43
+
44
+ declare class AgentContext {
45
+ readonly sub: string;
46
+ readonly svc: string;
47
+ readonly roles: readonly string[];
48
+ readonly orgId: string | undefined;
49
+ readonly teamId: string | undefined;
50
+ readonly raw: DirxTokenPayload;
51
+ constructor(payload: DirxTokenPayload);
52
+ hasRole(role: string): boolean;
53
+ isAgent(): boolean;
54
+ isAdmin(): boolean;
55
+ /** Token expiry as Date, or null if no exp claim. */
56
+ get expiresAt(): Date | null;
57
+ }
58
+
59
+ export { AgentContext as A, type DirxTokenPayload as D, type JwksClientOptions as J, JwksClient as a };
package/dist/index.cjs ADDED
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AgentContext: () => AgentContext,
24
+ DirxError: () => DirxError,
25
+ DirxErrorCode: () => DirxErrorCode,
26
+ Guard: () => Guard,
27
+ JwksClient: () => JwksClient,
28
+ createGuard: () => createGuard
29
+ });
30
+ module.exports = __toCommonJS(index_exports);
31
+
32
+ // src/auth/jwks.ts
33
+ var import_jose = require("jose");
34
+
35
+ // src/errors.ts
36
+ var DirxErrorCode = {
37
+ UNAUTHORIZED: "UNAUTHORIZED",
38
+ FORBIDDEN: "FORBIDDEN",
39
+ NOT_FOUND: "NOT_FOUND",
40
+ BAD_REQUEST: "BAD_REQUEST",
41
+ RATE_LIMITED: "RATE_LIMITED",
42
+ UPSTREAM_ERROR: "UPSTREAM_ERROR",
43
+ INTERNAL: "INTERNAL",
44
+ TOKEN_EXPIRED: "TOKEN_EXPIRED",
45
+ TOKEN_INVALID: "TOKEN_INVALID",
46
+ JWKS_FETCH_FAILED: "JWKS_FETCH_FAILED"
47
+ };
48
+ var HTTP_STATUS = {
49
+ UNAUTHORIZED: 401,
50
+ FORBIDDEN: 403,
51
+ NOT_FOUND: 404,
52
+ BAD_REQUEST: 400,
53
+ RATE_LIMITED: 429,
54
+ UPSTREAM_ERROR: 502,
55
+ INTERNAL: 500,
56
+ TOKEN_EXPIRED: 401,
57
+ TOKEN_INVALID: 401,
58
+ JWKS_FETCH_FAILED: 502
59
+ };
60
+ var DirxError = class extends Error {
61
+ code;
62
+ statusCode;
63
+ constructor(code, message) {
64
+ super(message);
65
+ this.name = "DirxError";
66
+ this.code = code;
67
+ this.statusCode = HTTP_STATUS[code];
68
+ }
69
+ toJSON() {
70
+ return {
71
+ code: this.code,
72
+ message: this.message,
73
+ statusCode: this.statusCode
74
+ };
75
+ }
76
+ };
77
+
78
+ // src/auth/jwks.ts
79
+ var JwksClient = class {
80
+ jwks;
81
+ issuer;
82
+ audience;
83
+ constructor(options) {
84
+ const jwksUrl = options?.jwksUrl ?? "https://api.dirx.ai/.well-known/jwks.json";
85
+ this.issuer = options?.issuer ?? "https://api.dirx.ai";
86
+ this.audience = options?.audience ?? "dirx";
87
+ this.jwks = (0, import_jose.createRemoteJWKSet)(new URL(jwksUrl));
88
+ }
89
+ /**
90
+ * Verify a JWT token against the JWKS endpoint.
91
+ * Returns the decoded payload on success, throws DirxError on failure.
92
+ */
93
+ async verify(token) {
94
+ try {
95
+ const { payload } = await (0, import_jose.jwtVerify)(token, this.jwks, {
96
+ issuer: this.issuer,
97
+ audience: this.audience
98
+ });
99
+ return payload;
100
+ } catch (err) {
101
+ const message = err instanceof Error ? err.message : String(err);
102
+ if (message.includes("expired")) {
103
+ throw new DirxError(
104
+ DirxErrorCode.TOKEN_EXPIRED,
105
+ "Token has expired"
106
+ );
107
+ }
108
+ throw new DirxError(
109
+ DirxErrorCode.TOKEN_INVALID,
110
+ `Token verification failed: ${message}`
111
+ );
112
+ }
113
+ }
114
+ };
115
+
116
+ // src/auth/context.ts
117
+ var AgentContext = class {
118
+ sub;
119
+ svc;
120
+ roles;
121
+ orgId;
122
+ teamId;
123
+ raw;
124
+ constructor(payload) {
125
+ this.sub = payload.sub;
126
+ this.svc = payload.svc ?? "unknown";
127
+ this.roles = Object.freeze(payload.roles ?? []);
128
+ this.orgId = payload.org_id;
129
+ this.teamId = payload.team_id;
130
+ this.raw = payload;
131
+ }
132
+ hasRole(role) {
133
+ return this.roles.includes(role);
134
+ }
135
+ isAgent() {
136
+ return this.hasRole("agent");
137
+ }
138
+ isAdmin() {
139
+ return this.hasRole("admin");
140
+ }
141
+ /** Token expiry as Date, or null if no exp claim. */
142
+ get expiresAt() {
143
+ return this.raw.exp ? new Date(this.raw.exp * 1e3) : null;
144
+ }
145
+ };
146
+
147
+ // src/middleware/guard.ts
148
+ var Guard = class {
149
+ client;
150
+ required;
151
+ constructor(options) {
152
+ this.client = new JwksClient(options);
153
+ this.required = options?.required !== false;
154
+ }
155
+ /**
156
+ * Authenticate a raw Bearer token string.
157
+ * Returns AgentContext on success.
158
+ */
159
+ async authenticate(token) {
160
+ const payload = await this.client.verify(token);
161
+ return new AgentContext(payload);
162
+ }
163
+ /**
164
+ * Extract Bearer token from an Authorization header value.
165
+ * Returns null if not present or malformed.
166
+ */
167
+ extractToken(authHeader) {
168
+ if (!authHeader) return null;
169
+ const parts = authHeader.split(" ");
170
+ if (parts.length !== 2 || parts[0].toLowerCase() !== "bearer") {
171
+ return null;
172
+ }
173
+ return parts[1];
174
+ }
175
+ /**
176
+ * Full flow: extract token from header → verify → return AgentContext.
177
+ * Throws DirxError if required and no/invalid token.
178
+ */
179
+ async fromHeader(authHeader) {
180
+ const token = this.extractToken(authHeader);
181
+ if (!token) {
182
+ if (this.required) {
183
+ throw new DirxError(
184
+ DirxErrorCode.UNAUTHORIZED,
185
+ "Missing or malformed Authorization header"
186
+ );
187
+ }
188
+ return null;
189
+ }
190
+ return this.authenticate(token);
191
+ }
192
+ /**
193
+ * Express/Connect-style middleware factory.
194
+ * Attaches `req.agent` (AgentContext) on success.
195
+ */
196
+ express() {
197
+ return async (req, res, next) => {
198
+ try {
199
+ const ctx = await this.fromHeader(req.headers.authorization);
200
+ if (ctx) {
201
+ req.agent = ctx;
202
+ }
203
+ next();
204
+ } catch (err) {
205
+ if (err instanceof DirxError) {
206
+ res.status(err.statusCode).json({
207
+ ok: false,
208
+ error: { code: err.code, message: err.message }
209
+ });
210
+ return;
211
+ }
212
+ next(err);
213
+ }
214
+ };
215
+ }
216
+ };
217
+ function createGuard(options) {
218
+ return new Guard(options);
219
+ }
220
+ // Annotate the CommonJS export names for ESM import in node:
221
+ 0 && (module.exports = {
222
+ AgentContext,
223
+ DirxError,
224
+ DirxErrorCode,
225
+ Guard,
226
+ JwksClient,
227
+ createGuard
228
+ });
@@ -0,0 +1,90 @@
1
+ import { J as JwksClientOptions, A as AgentContext } from './context-C7RRNS5U.cjs';
2
+ export { D as DirxTokenPayload, a as JwksClient } from './context-C7RRNS5U.cjs';
3
+ import 'jose';
4
+
5
+ /**
6
+ * Guard middleware — extracts and verifies Bearer tokens from incoming requests.
7
+ *
8
+ * Framework-agnostic: works with any Node.js HTTP framework that provides
9
+ * standard Request/Response objects (Express, Hono, Fastify, etc.).
10
+ *
11
+ * Usage:
12
+ * import { createGuard } from "@dirxai/core";
13
+ * const guard = createGuard({ jwksUrl: "..." });
14
+ *
15
+ * // Express
16
+ * app.use(guard.express());
17
+ *
18
+ * // Generic (any framework)
19
+ * const ctx = await guard.authenticate(bearerToken);
20
+ */
21
+
22
+ interface GuardOptions extends JwksClientOptions {
23
+ /** If true, requests without a token are rejected. Default: true */
24
+ required?: boolean;
25
+ }
26
+ declare class Guard {
27
+ private readonly client;
28
+ private readonly required;
29
+ constructor(options?: GuardOptions);
30
+ /**
31
+ * Authenticate a raw Bearer token string.
32
+ * Returns AgentContext on success.
33
+ */
34
+ authenticate(token: string): Promise<AgentContext>;
35
+ /**
36
+ * Extract Bearer token from an Authorization header value.
37
+ * Returns null if not present or malformed.
38
+ */
39
+ extractToken(authHeader: string | null | undefined): string | null;
40
+ /**
41
+ * Full flow: extract token from header → verify → return AgentContext.
42
+ * Throws DirxError if required and no/invalid token.
43
+ */
44
+ fromHeader(authHeader: string | null | undefined): Promise<AgentContext | null>;
45
+ /**
46
+ * Express/Connect-style middleware factory.
47
+ * Attaches `req.agent` (AgentContext) on success.
48
+ */
49
+ express(): (req: {
50
+ headers: Record<string, string | undefined>;
51
+ agent?: AgentContext;
52
+ }, res: {
53
+ status: (code: number) => {
54
+ json: (body: unknown) => void;
55
+ };
56
+ }, next: (err?: unknown) => void) => Promise<void>;
57
+ }
58
+ declare function createGuard(options?: GuardOptions): Guard;
59
+
60
+ /**
61
+ * DirX error codes and typed error class.
62
+ *
63
+ * Mirrors the server-side DirxEnvelope error model so SDK consumers
64
+ * can handle errors uniformly across CLI, SDK, and server.
65
+ */
66
+ declare const DirxErrorCode: {
67
+ readonly UNAUTHORIZED: "UNAUTHORIZED";
68
+ readonly FORBIDDEN: "FORBIDDEN";
69
+ readonly NOT_FOUND: "NOT_FOUND";
70
+ readonly BAD_REQUEST: "BAD_REQUEST";
71
+ readonly RATE_LIMITED: "RATE_LIMITED";
72
+ readonly UPSTREAM_ERROR: "UPSTREAM_ERROR";
73
+ readonly INTERNAL: "INTERNAL";
74
+ readonly TOKEN_EXPIRED: "TOKEN_EXPIRED";
75
+ readonly TOKEN_INVALID: "TOKEN_INVALID";
76
+ readonly JWKS_FETCH_FAILED: "JWKS_FETCH_FAILED";
77
+ };
78
+ type DirxErrorCode = (typeof DirxErrorCode)[keyof typeof DirxErrorCode];
79
+ declare class DirxError extends Error {
80
+ readonly code: DirxErrorCode;
81
+ readonly statusCode: number;
82
+ constructor(code: DirxErrorCode, message: string);
83
+ toJSON(): {
84
+ code: DirxErrorCode;
85
+ message: string;
86
+ statusCode: number;
87
+ };
88
+ }
89
+
90
+ export { AgentContext, DirxError, DirxErrorCode, Guard, type GuardOptions, JwksClientOptions, createGuard };
@@ -0,0 +1,90 @@
1
+ import { J as JwksClientOptions, A as AgentContext } from './context-C7RRNS5U.js';
2
+ export { D as DirxTokenPayload, a as JwksClient } from './context-C7RRNS5U.js';
3
+ import 'jose';
4
+
5
+ /**
6
+ * Guard middleware — extracts and verifies Bearer tokens from incoming requests.
7
+ *
8
+ * Framework-agnostic: works with any Node.js HTTP framework that provides
9
+ * standard Request/Response objects (Express, Hono, Fastify, etc.).
10
+ *
11
+ * Usage:
12
+ * import { createGuard } from "@dirxai/core";
13
+ * const guard = createGuard({ jwksUrl: "..." });
14
+ *
15
+ * // Express
16
+ * app.use(guard.express());
17
+ *
18
+ * // Generic (any framework)
19
+ * const ctx = await guard.authenticate(bearerToken);
20
+ */
21
+
22
+ interface GuardOptions extends JwksClientOptions {
23
+ /** If true, requests without a token are rejected. Default: true */
24
+ required?: boolean;
25
+ }
26
+ declare class Guard {
27
+ private readonly client;
28
+ private readonly required;
29
+ constructor(options?: GuardOptions);
30
+ /**
31
+ * Authenticate a raw Bearer token string.
32
+ * Returns AgentContext on success.
33
+ */
34
+ authenticate(token: string): Promise<AgentContext>;
35
+ /**
36
+ * Extract Bearer token from an Authorization header value.
37
+ * Returns null if not present or malformed.
38
+ */
39
+ extractToken(authHeader: string | null | undefined): string | null;
40
+ /**
41
+ * Full flow: extract token from header → verify → return AgentContext.
42
+ * Throws DirxError if required and no/invalid token.
43
+ */
44
+ fromHeader(authHeader: string | null | undefined): Promise<AgentContext | null>;
45
+ /**
46
+ * Express/Connect-style middleware factory.
47
+ * Attaches `req.agent` (AgentContext) on success.
48
+ */
49
+ express(): (req: {
50
+ headers: Record<string, string | undefined>;
51
+ agent?: AgentContext;
52
+ }, res: {
53
+ status: (code: number) => {
54
+ json: (body: unknown) => void;
55
+ };
56
+ }, next: (err?: unknown) => void) => Promise<void>;
57
+ }
58
+ declare function createGuard(options?: GuardOptions): Guard;
59
+
60
+ /**
61
+ * DirX error codes and typed error class.
62
+ *
63
+ * Mirrors the server-side DirxEnvelope error model so SDK consumers
64
+ * can handle errors uniformly across CLI, SDK, and server.
65
+ */
66
+ declare const DirxErrorCode: {
67
+ readonly UNAUTHORIZED: "UNAUTHORIZED";
68
+ readonly FORBIDDEN: "FORBIDDEN";
69
+ readonly NOT_FOUND: "NOT_FOUND";
70
+ readonly BAD_REQUEST: "BAD_REQUEST";
71
+ readonly RATE_LIMITED: "RATE_LIMITED";
72
+ readonly UPSTREAM_ERROR: "UPSTREAM_ERROR";
73
+ readonly INTERNAL: "INTERNAL";
74
+ readonly TOKEN_EXPIRED: "TOKEN_EXPIRED";
75
+ readonly TOKEN_INVALID: "TOKEN_INVALID";
76
+ readonly JWKS_FETCH_FAILED: "JWKS_FETCH_FAILED";
77
+ };
78
+ type DirxErrorCode = (typeof DirxErrorCode)[keyof typeof DirxErrorCode];
79
+ declare class DirxError extends Error {
80
+ readonly code: DirxErrorCode;
81
+ readonly statusCode: number;
82
+ constructor(code: DirxErrorCode, message: string);
83
+ toJSON(): {
84
+ code: DirxErrorCode;
85
+ message: string;
86
+ statusCode: number;
87
+ };
88
+ }
89
+
90
+ export { AgentContext, DirxError, DirxErrorCode, Guard, type GuardOptions, JwksClientOptions, createGuard };
package/dist/index.js ADDED
@@ -0,0 +1,169 @@
1
+ import {
2
+ AgentContext
3
+ } from "./chunk-5BEMU43U.js";
4
+
5
+ // src/auth/jwks.ts
6
+ import { createRemoteJWKSet, jwtVerify } from "jose";
7
+
8
+ // src/errors.ts
9
+ var DirxErrorCode = {
10
+ UNAUTHORIZED: "UNAUTHORIZED",
11
+ FORBIDDEN: "FORBIDDEN",
12
+ NOT_FOUND: "NOT_FOUND",
13
+ BAD_REQUEST: "BAD_REQUEST",
14
+ RATE_LIMITED: "RATE_LIMITED",
15
+ UPSTREAM_ERROR: "UPSTREAM_ERROR",
16
+ INTERNAL: "INTERNAL",
17
+ TOKEN_EXPIRED: "TOKEN_EXPIRED",
18
+ TOKEN_INVALID: "TOKEN_INVALID",
19
+ JWKS_FETCH_FAILED: "JWKS_FETCH_FAILED"
20
+ };
21
+ var HTTP_STATUS = {
22
+ UNAUTHORIZED: 401,
23
+ FORBIDDEN: 403,
24
+ NOT_FOUND: 404,
25
+ BAD_REQUEST: 400,
26
+ RATE_LIMITED: 429,
27
+ UPSTREAM_ERROR: 502,
28
+ INTERNAL: 500,
29
+ TOKEN_EXPIRED: 401,
30
+ TOKEN_INVALID: 401,
31
+ JWKS_FETCH_FAILED: 502
32
+ };
33
+ var DirxError = class extends Error {
34
+ code;
35
+ statusCode;
36
+ constructor(code, message) {
37
+ super(message);
38
+ this.name = "DirxError";
39
+ this.code = code;
40
+ this.statusCode = HTTP_STATUS[code];
41
+ }
42
+ toJSON() {
43
+ return {
44
+ code: this.code,
45
+ message: this.message,
46
+ statusCode: this.statusCode
47
+ };
48
+ }
49
+ };
50
+
51
+ // src/auth/jwks.ts
52
+ var JwksClient = class {
53
+ jwks;
54
+ issuer;
55
+ audience;
56
+ constructor(options) {
57
+ const jwksUrl = options?.jwksUrl ?? "https://api.dirx.ai/.well-known/jwks.json";
58
+ this.issuer = options?.issuer ?? "https://api.dirx.ai";
59
+ this.audience = options?.audience ?? "dirx";
60
+ this.jwks = createRemoteJWKSet(new URL(jwksUrl));
61
+ }
62
+ /**
63
+ * Verify a JWT token against the JWKS endpoint.
64
+ * Returns the decoded payload on success, throws DirxError on failure.
65
+ */
66
+ async verify(token) {
67
+ try {
68
+ const { payload } = await jwtVerify(token, this.jwks, {
69
+ issuer: this.issuer,
70
+ audience: this.audience
71
+ });
72
+ return payload;
73
+ } catch (err) {
74
+ const message = err instanceof Error ? err.message : String(err);
75
+ if (message.includes("expired")) {
76
+ throw new DirxError(
77
+ DirxErrorCode.TOKEN_EXPIRED,
78
+ "Token has expired"
79
+ );
80
+ }
81
+ throw new DirxError(
82
+ DirxErrorCode.TOKEN_INVALID,
83
+ `Token verification failed: ${message}`
84
+ );
85
+ }
86
+ }
87
+ };
88
+
89
+ // src/middleware/guard.ts
90
+ var Guard = class {
91
+ client;
92
+ required;
93
+ constructor(options) {
94
+ this.client = new JwksClient(options);
95
+ this.required = options?.required !== false;
96
+ }
97
+ /**
98
+ * Authenticate a raw Bearer token string.
99
+ * Returns AgentContext on success.
100
+ */
101
+ async authenticate(token) {
102
+ const payload = await this.client.verify(token);
103
+ return new AgentContext(payload);
104
+ }
105
+ /**
106
+ * Extract Bearer token from an Authorization header value.
107
+ * Returns null if not present or malformed.
108
+ */
109
+ extractToken(authHeader) {
110
+ if (!authHeader) return null;
111
+ const parts = authHeader.split(" ");
112
+ if (parts.length !== 2 || parts[0].toLowerCase() !== "bearer") {
113
+ return null;
114
+ }
115
+ return parts[1];
116
+ }
117
+ /**
118
+ * Full flow: extract token from header → verify → return AgentContext.
119
+ * Throws DirxError if required and no/invalid token.
120
+ */
121
+ async fromHeader(authHeader) {
122
+ const token = this.extractToken(authHeader);
123
+ if (!token) {
124
+ if (this.required) {
125
+ throw new DirxError(
126
+ DirxErrorCode.UNAUTHORIZED,
127
+ "Missing or malformed Authorization header"
128
+ );
129
+ }
130
+ return null;
131
+ }
132
+ return this.authenticate(token);
133
+ }
134
+ /**
135
+ * Express/Connect-style middleware factory.
136
+ * Attaches `req.agent` (AgentContext) on success.
137
+ */
138
+ express() {
139
+ return async (req, res, next) => {
140
+ try {
141
+ const ctx = await this.fromHeader(req.headers.authorization);
142
+ if (ctx) {
143
+ req.agent = ctx;
144
+ }
145
+ next();
146
+ } catch (err) {
147
+ if (err instanceof DirxError) {
148
+ res.status(err.statusCode).json({
149
+ ok: false,
150
+ error: { code: err.code, message: err.message }
151
+ });
152
+ return;
153
+ }
154
+ next(err);
155
+ }
156
+ };
157
+ }
158
+ };
159
+ function createGuard(options) {
160
+ return new Guard(options);
161
+ }
162
+ export {
163
+ AgentContext,
164
+ DirxError,
165
+ DirxErrorCode,
166
+ Guard,
167
+ JwksClient,
168
+ createGuard
169
+ };
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/testing.ts
21
+ var testing_exports = {};
22
+ __export(testing_exports, {
23
+ AgentContext: () => AgentContext,
24
+ createMockAgent: () => createMockAgent
25
+ });
26
+ module.exports = __toCommonJS(testing_exports);
27
+
28
+ // src/auth/context.ts
29
+ var AgentContext = class {
30
+ sub;
31
+ svc;
32
+ roles;
33
+ orgId;
34
+ teamId;
35
+ raw;
36
+ constructor(payload) {
37
+ this.sub = payload.sub;
38
+ this.svc = payload.svc ?? "unknown";
39
+ this.roles = Object.freeze(payload.roles ?? []);
40
+ this.orgId = payload.org_id;
41
+ this.teamId = payload.team_id;
42
+ this.raw = payload;
43
+ }
44
+ hasRole(role) {
45
+ return this.roles.includes(role);
46
+ }
47
+ isAgent() {
48
+ return this.hasRole("agent");
49
+ }
50
+ isAdmin() {
51
+ return this.hasRole("admin");
52
+ }
53
+ /** Token expiry as Date, or null if no exp claim. */
54
+ get expiresAt() {
55
+ return this.raw.exp ? new Date(this.raw.exp * 1e3) : null;
56
+ }
57
+ };
58
+
59
+ // src/testing.ts
60
+ function createMockAgent(options) {
61
+ const now = Math.floor(Date.now() / 1e3);
62
+ const payload = {
63
+ sub: options?.sub ?? "test-agent",
64
+ svc: options?.svc ?? "test",
65
+ roles: options?.roles ?? ["agent"],
66
+ org_id: options?.orgId,
67
+ team_id: options?.teamId,
68
+ iat: now,
69
+ exp: now + (options?.expiresInSeconds ?? 3600),
70
+ iss: "https://api.dirx.ai",
71
+ aud: "dirx"
72
+ };
73
+ return new AgentContext(payload);
74
+ }
75
+ // Annotate the CommonJS export names for ESM import in node:
76
+ 0 && (module.exports = {
77
+ AgentContext,
78
+ createMockAgent
79
+ });
@@ -0,0 +1,26 @@
1
+ import { A as AgentContext } from './context-C7RRNS5U.cjs';
2
+ export { D as DirxTokenPayload } from './context-C7RRNS5U.cjs';
3
+ import 'jose';
4
+
5
+ /**
6
+ * @dirxai/core/testing — Test utilities for DirX SDK consumers.
7
+ *
8
+ * Provides helpers to create mock AgentContext and tokens for unit tests
9
+ * without requiring a real JWKS endpoint.
10
+ */
11
+
12
+ interface MockAgentOptions {
13
+ sub?: string;
14
+ svc?: string;
15
+ roles?: string[];
16
+ orgId?: string;
17
+ teamId?: string;
18
+ expiresInSeconds?: number;
19
+ }
20
+ /**
21
+ * Create a mock AgentContext for testing.
22
+ * No real JWT or JWKS involved — purely in-memory.
23
+ */
24
+ declare function createMockAgent(options?: MockAgentOptions): AgentContext;
25
+
26
+ export { AgentContext, type MockAgentOptions, createMockAgent };
@@ -0,0 +1,26 @@
1
+ import { A as AgentContext } from './context-C7RRNS5U.js';
2
+ export { D as DirxTokenPayload } from './context-C7RRNS5U.js';
3
+ import 'jose';
4
+
5
+ /**
6
+ * @dirxai/core/testing — Test utilities for DirX SDK consumers.
7
+ *
8
+ * Provides helpers to create mock AgentContext and tokens for unit tests
9
+ * without requiring a real JWKS endpoint.
10
+ */
11
+
12
+ interface MockAgentOptions {
13
+ sub?: string;
14
+ svc?: string;
15
+ roles?: string[];
16
+ orgId?: string;
17
+ teamId?: string;
18
+ expiresInSeconds?: number;
19
+ }
20
+ /**
21
+ * Create a mock AgentContext for testing.
22
+ * No real JWT or JWKS involved — purely in-memory.
23
+ */
24
+ declare function createMockAgent(options?: MockAgentOptions): AgentContext;
25
+
26
+ export { AgentContext, type MockAgentOptions, createMockAgent };
@@ -0,0 +1,24 @@
1
+ import {
2
+ AgentContext
3
+ } from "./chunk-5BEMU43U.js";
4
+
5
+ // src/testing.ts
6
+ function createMockAgent(options) {
7
+ const now = Math.floor(Date.now() / 1e3);
8
+ const payload = {
9
+ sub: options?.sub ?? "test-agent",
10
+ svc: options?.svc ?? "test",
11
+ roles: options?.roles ?? ["agent"],
12
+ org_id: options?.orgId,
13
+ team_id: options?.teamId,
14
+ iat: now,
15
+ exp: now + (options?.expiresInSeconds ?? 3600),
16
+ iss: "https://api.dirx.ai",
17
+ aud: "dirx"
18
+ };
19
+ return new AgentContext(payload);
20
+ }
21
+ export {
22
+ AgentContext,
23
+ createMockAgent
24
+ };
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@dirxai/core",
3
+ "version": "0.3.0",
4
+ "description": "DirX server-side SDK — Guard middleware, JWKS auth, AgentContext, error codes",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ },
16
+ "./testing": {
17
+ "types": "./dist/testing.d.ts",
18
+ "import": "./dist/testing.js",
19
+ "require": "./dist/testing.cjs"
20
+ }
21
+ },
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "dev": "tsup --watch"
25
+ },
26
+ "dependencies": {
27
+ "jose": "^6.1.3"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/dirxai/dirx.git",
32
+ "directory": "packages/core"
33
+ },
34
+ "homepage": "https://dirx.ai",
35
+ "keywords": [
36
+ "dirx",
37
+ "agent",
38
+ "sdk",
39
+ "gateway",
40
+ "guard",
41
+ "jwks",
42
+ "jwt"
43
+ ],
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "files": [
48
+ "dist"
49
+ ],
50
+ "engines": {
51
+ "node": ">=18"
52
+ }
53
+ }