@lelu-auth/lelu 0.1.4 → 0.1.9

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Abenezer <abenezergetachew0923@gmail.com>
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Abenezer <abenezergetachew0923@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,96 +1,55 @@
1
- [![Lelu logo](https://ui-seven-amber.vercel.app/logo.svg)](https://ui-seven-amber.vercel.app/)
2
-
3
- # Lelu
4
-
5
- The TypeScript SDK for Lelu the confidence-aware authorization engine for autonomous AI agents.
6
-
7
- Lelu provides confidence-aware access control, human-in-the-loop approvals, and SOC 2-ready audit trails for your autonomous agents.
8
-
9
- ## Installation
10
-
11
- ```bash
12
- npm install @lelu-auth/lelu
13
- ```
14
-
15
- ## Start Dashboard (Localhost)
16
-
17
- After installing the package, start the local dashboard stack with one command:
18
-
19
- ```bash
20
- npx @lelu-auth/lelu dashboard
21
- ```
22
-
23
- Then open:
24
-
25
- ```text
26
- http://localhost:3002/audit
27
- ```
28
-
29
- This command clones/updates the Lelu stack in `~/.lelu-stack` and runs `docker compose up -d --build`.
30
-
31
- Or run the public Lelu engine image:
32
-
33
- ```bash
34
- docker pull abenezer0923/lelu-engine:latest
35
- docker run --rm -p 8083:8080 abenezer0923/lelu-engine:latest
36
- ```
37
-
38
- ## Docker Support
39
-
40
- Lelu works in Dockerized apps.
41
-
42
- The SDK resolves engine URL in this order:
43
-
44
- 1. `baseUrl` passed to `createClient(...)`
45
- 2. `LELU_BASE_URL` environment variable
46
- 3. `http://localhost:8080` fallback
47
-
48
- Example for containers:
49
-
50
- ```bash
51
- LELU_BASE_URL=http://host.docker.internal:8083
52
- ```
53
-
54
- ## Quick Start
55
-
56
- ```typescript
57
- import { createClient } from "@lelu-auth/lelu";
58
-
59
- // Initialize the client
60
- const lelu = createClient({
61
- baseUrl: "http://localhost:8083"
62
- });
63
-
64
- // Authorize an agent action
65
- async function runAgent() {
66
- const { allowed, reason } = await lelu.agentAuthorize({
67
- agentId: "agent-123",
68
- action: "read_database",
69
- resource: "users_table",
70
- context: {
71
- confidence: 0.95
72
- }
73
- });
74
-
75
- if (allowed) {
76
- console.log("Action permitted!");
77
- } else {
78
- console.log("Action denied:", reason);
79
- }
80
- }
81
- ```
82
-
83
- ## Features
84
-
85
- - **Confidence-Aware**: Dynamically adjust permissions based on the AI agent's confidence level.
86
- - **Human-in-the-loop**: Require human approval for low-confidence or high-risk actions.
87
- - **Audit Trails**: SOC 2-ready logging of all agent decisions and actions.
88
- - **Framework Agnostic**: Works with LangChain, AutoGPT, or custom agent frameworks.
89
-
90
- ## Documentation
91
-
92
- For full documentation, visit [https://ui-seven-amber.vercel.app/](https://ui-seven-amber.vercel.app/).
93
-
94
- ## License
95
-
96
- MIT
1
+ # Lelu
2
+
3
+ The TypeScript SDK for Lelu — the confidence-aware authorization engine for autonomous AI agents.
4
+
5
+ Lelu provides confidence-aware access control, human-in-the-loop approvals, and SOC 2-ready audit trails for your autonomous agents.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @lelu-auth/lelu
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { createClient } from "@lelu-auth/lelu";
17
+
18
+ // Initialize the client
19
+ const lelu = createClient({
20
+ baseUrl: "http://localhost:8082"
21
+ });
22
+
23
+ // Authorize an agent action
24
+ async function runAgent() {
25
+ const { allowed, reason } = await lelu.agentAuthorize({
26
+ agentId: "agent-123",
27
+ action: "read_database",
28
+ resource: "users_table",
29
+ context: {
30
+ confidence: 0.95
31
+ }
32
+ });
33
+
34
+ if (allowed) {
35
+ console.log("Action permitted!");
36
+ } else {
37
+ console.log("Action denied:", reason);
38
+ }
39
+ }
40
+ ```
41
+
42
+ ## Features
43
+
44
+ - **Confidence-Aware**: Dynamically adjust permissions based on the AI agent's confidence level.
45
+ - **Human-in-the-loop**: Require human approval for low-confidence or high-risk actions.
46
+ - **Audit Trails**: SOC 2-ready logging of all agent decisions and actions.
47
+ - **Framework Agnostic**: Works with LangChain, AutoGPT, or custom agent frameworks.
48
+
49
+ ## Documentation
50
+
51
+ For full documentation, visit [https://github.com/lelu-auth/lelu](https://github.com/lelu-auth/lelu).
52
+
53
+ ## License
54
+
55
+ MIT
@@ -156,7 +156,7 @@ type AgentAuthRequest = z.infer<typeof AgentAuthRequestSchema>;
156
156
  type AgentContext = z.infer<typeof AgentContextSchema>;
157
157
  type MintTokenRequest = z.infer<typeof MintTokenRequestSchema>;
158
158
  interface ClientConfig {
159
- /** Base URL of the Auth Permission Engine (defaults to LELU_BASE_URL env var, else http://localhost:8080) */
159
+ /** Base URL of the Auth Permission Engine (default: http://localhost:8080) */
160
160
  baseUrl?: string;
161
161
  /** Request timeout in milliseconds (default: 5000) */
162
162
  timeoutMs?: number;
@@ -156,7 +156,7 @@ type AgentAuthRequest = z.infer<typeof AgentAuthRequestSchema>;
156
156
  type AgentContext = z.infer<typeof AgentContextSchema>;
157
157
  type MintTokenRequest = z.infer<typeof MintTokenRequestSchema>;
158
158
  interface ClientConfig {
159
- /** Base URL of the Auth Permission Engine (defaults to LELU_BASE_URL env var, else http://localhost:8080) */
159
+ /** Base URL of the Auth Permission Engine (default: http://localhost:8080) */
160
160
  baseUrl?: string;
161
161
  /** Request timeout in milliseconds (default: 5000) */
162
162
  timeoutMs?: number;
@@ -1,5 +1,5 @@
1
1
  import { RequestHandler } from 'express';
2
- import { L as LeluClient } from '../client-DL75VVER.mjs';
2
+ import { L as LeluClient } from '../client-BD9h8CBT.mjs';
3
3
  import 'zod';
4
4
 
5
5
  interface AuthorizeOptions {
@@ -1,5 +1,5 @@
1
1
  import { RequestHandler } from 'express';
2
- import { L as LeluClient } from '../client-DL75VVER.js';
2
+ import { L as LeluClient } from '../client-BD9h8CBT.js';
3
3
  import 'zod';
4
4
 
5
5
  interface AuthorizeOptions {
@@ -51,8 +51,7 @@ var LeluClient = class {
51
51
  timeoutMs;
52
52
  apiKey;
53
53
  constructor(cfg = {}) {
54
- const envBaseUrl = typeof process !== "undefined" && process.env ? process.env["LELU_BASE_URL"] : void 0;
55
- this.baseUrl = (cfg.baseUrl ?? envBaseUrl ?? "http://localhost:8080").replace(/\/$/, "");
54
+ this.baseUrl = (cfg.baseUrl ?? "http://localhost:8080").replace(/\/$/, "");
56
55
  this.timeoutMs = cfg.timeoutMs ?? 5e3;
57
56
  this.apiKey = cfg.apiKey;
58
57
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types.ts","../../src/client.ts","../../src/express/index.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from \"zod\";\r\n\r\n// ─── Request / Response schemas ───────────────────────────────────────────────\r\n\r\nexport const AuthRequestSchema = z.object({\r\n userId: z.string().min(1, \"userId is required\"),\r\n action: z.string().min(1, \"action is required\"),\r\n resource: z.record(z.string()).optional(),\r\n});\r\n\r\nexport const AgentContextSchema = z.object({\r\n /** LLM confidence score — 0.0 to 1.0 */\r\n confidence: z.number().min(0).max(1),\r\n /** User the agent is acting on behalf of */\r\n actingFor: z.string().optional(),\r\n /** Requested agent scope */\r\n scope: z.string().optional(),\r\n});\r\n\r\nexport const AgentAuthRequestSchema = z.object({\r\n actor: z.string().min(1, \"actor is required\"),\r\n action: z.string().min(1, \"action is required\"),\r\n resource: z.record(z.string()).optional(),\r\n context: AgentContextSchema,\r\n});\r\n\r\nexport const MintTokenRequestSchema = z.object({\r\n scope: z.string().min(1),\r\n actingFor: z.string().optional(),\r\n ttlSeconds: z.number().int().positive().optional(),\r\n});\r\n\r\nexport const DelegateScopeRequestSchema = z.object({\r\n delegator: z.string().min(1, \"delegator is required\"),\r\n delegatee: z.string().min(1, \"delegatee is required\"),\r\n scopedTo: z.array(z.string().min(1)).optional(),\r\n ttlSeconds: z.number().int().positive().optional(),\r\n confidence: z.number().min(0).max(1).optional(),\r\n actingFor: z.string().optional(),\r\n tenantId: z.string().optional(),\r\n});\r\n\r\n// ─── Decision types ───────────────────────────────────────────────────────────\r\n\r\nexport interface AuthDecision {\r\n allowed: boolean;\r\n reason: string;\r\n traceId: string;\r\n}\r\n\r\nexport interface AgentAuthDecision {\r\n allowed: boolean;\r\n reason: string;\r\n traceId: string;\r\n downgradedScope: string | undefined;\r\n requiresHumanReview: boolean;\r\n confidenceUsed: number;\r\n}\r\n\r\nexport interface MintTokenResult {\r\n token: string;\r\n tokenId: string;\r\n expiresAt: Date;\r\n}\r\n\r\nexport interface DelegateScopeRequest {\r\n /** Agent delegating the scope */\r\n delegator: string;\r\n /** Agent receiving the constrained sub-scope */\r\n delegatee: string;\r\n /** Actions to grant (must be subset of policy's can_delegate.scoped_to) */\r\n scopedTo?: string[];\r\n /** Token TTL in seconds — capped by the policy's max_ttl_seconds */\r\n ttlSeconds?: number;\r\n /** Delegator's confidence score — checked against require_confidence_above */\r\n confidence?: number;\r\n /** User the delegated agent acts on behalf of */\r\n actingFor?: string;\r\n tenantId?: string;\r\n}\r\n\r\nexport interface DelegateScopeResult {\r\n token: string;\r\n tokenId: string;\r\n expiresAt: Date;\r\n delegator: string;\r\n delegatee: string;\r\n grantedScopes: string[];\r\n traceId: string;\r\n}\r\n\r\nexport interface RevokeTokenResult {\r\n success: boolean;\r\n}\r\n\r\n// ─── Typed Input types ───────────────────────────────────────────────────────\r\n\r\nexport type AuthRequest = z.infer<typeof AuthRequestSchema>;\r\nexport type AgentAuthRequest = z.infer<typeof AgentAuthRequestSchema>;\r\nexport type AgentContext = z.infer<typeof AgentContextSchema>;\r\nexport type MintTokenRequest = z.infer<typeof MintTokenRequestSchema>;\r\n\r\n// ─── Client config ────────────────────────────────────────────────────────────\r\n\r\nexport interface ClientConfig {\r\n /** Base URL of the Auth Permission Engine (defaults to LELU_BASE_URL env var, else http://localhost:8080) */\r\n baseUrl?: string;\r\n /** Request timeout in milliseconds (default: 5000) */\r\n timeoutMs?: number;\r\n /** Optional bearer token for authenticating with the engine */\r\n apiKey?: string;\r\n}\r\n\r\n// ─── Error type ───────────────────────────────────────────────────────────────\r\n\r\nexport class AuthEngineError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly status?: number,\r\n public readonly details?: unknown\r\n ) {\r\n super(message);\r\n this.name = \"AuthEngineError\";\r\n }\r\n}\r\n","import {\r\n AuthEngineError,\r\n AuthRequestSchema,\r\n AgentAuthRequestSchema,\r\n MintTokenRequestSchema,\r\n DelegateScopeRequestSchema,\r\n type AuthDecision,\r\n type AgentAuthDecision,\r\n type MintTokenResult,\r\n type DelegateScopeResult,\r\n type DelegateScopeRequest,\r\n type RevokeTokenResult,\r\n type AuthRequest,\r\n type AgentAuthRequest,\r\n type MintTokenRequest,\r\n type ClientConfig,\r\n} from \"./types.js\";\r\n\r\n// ─── Client ───────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * LeluClient is the core SDK entry-point. It communicates with the local\r\n * Auth Permission Engine sidecar over HTTP/JSON.\r\n *\r\n * @example\r\n * ```ts\r\n * const lelu = new LeluClient({ baseUrl: \"http://localhost:8080\" });\r\n *\r\n * const decision = await lelu.agentAuthorize({\r\n * actor: \"invoice_bot\",\r\n * action: \"approve_refunds\",\r\n * context: { confidence: 0.92, actingFor: \"user_123\" },\r\n * });\r\n *\r\n * if (!decision.allowed) {\r\n * console.log(decision.reason);\r\n * }\r\n * ```\r\n */\r\nexport class LeluClient {\r\n private readonly baseUrl: string;\r\n private readonly timeoutMs: number;\r\n private readonly apiKey: string | undefined;\r\n\r\n constructor(cfg: ClientConfig = {}) {\r\n const envBaseUrl =\r\n typeof process !== \"undefined\" && process.env\r\n ? process.env[\"LELU_BASE_URL\"]\r\n : undefined;\r\n this.baseUrl = (cfg.baseUrl ?? envBaseUrl ?? \"http://localhost:8080\").replace(/\\/$/, \"\");\r\n this.timeoutMs = cfg.timeoutMs ?? 5_000;\r\n this.apiKey = cfg.apiKey;\r\n }\r\n\r\n // ── Human authorization ────────────────────────────────────────────────────\r\n\r\n /**\r\n * Checks whether a human user is permitted to perform an action.\r\n */\r\n async authorize(req: AuthRequest): Promise<AuthDecision> {\r\n const validated = AuthRequestSchema.parse(req);\r\n const body = {\r\n user_id: validated.userId,\r\n action: validated.action,\r\n resource: validated.resource,\r\n };\r\n const data = await this.post<{\r\n allowed: boolean;\r\n reason: string;\r\n trace_id: string;\r\n }>(\"/v1/authorize\", body);\r\n\r\n return {\r\n allowed: data.allowed,\r\n reason: data.reason,\r\n traceId: data.trace_id,\r\n };\r\n }\r\n\r\n // ── Agent authorization ────────────────────────────────────────────────────\r\n\r\n /**\r\n * Checks whether an AI agent is permitted to perform an action, taking the\r\n * confidence score into account (Confidence-Aware Auth ★).\r\n */\r\n async agentAuthorize(req: AgentAuthRequest): Promise<AgentAuthDecision> {\r\n const validated = AgentAuthRequestSchema.parse(req);\r\n const body = {\r\n actor: validated.actor,\r\n action: validated.action,\r\n resource: validated.resource,\r\n confidence: validated.context.confidence,\r\n acting_for: validated.context.actingFor,\r\n scope: validated.context.scope,\r\n };\r\n const data = await this.post<{\r\n allowed: boolean;\r\n reason: string;\r\n trace_id: string;\r\n downgraded_scope?: string;\r\n requires_human_review: boolean;\r\n confidence_used: number;\r\n }>(\"/v1/agent/authorize\", body);\r\n\r\n return {\r\n allowed: data.allowed,\r\n reason: data.reason,\r\n traceId: data.trace_id,\r\n downgradedScope: data.downgraded_scope,\r\n requiresHumanReview: data.requires_human_review,\r\n confidenceUsed: data.confidence_used,\r\n };\r\n }\r\n\r\n // ── JIT Token minting ──────────────────────────────────────────────────────\r\n\r\n /**\r\n * Mints a scoped JWT for an agent with an optional TTL.\r\n * Default TTL is 60 seconds.\r\n */\r\n async mintToken(req: MintTokenRequest): Promise<MintTokenResult> {\r\n const validated = MintTokenRequestSchema.parse(req);\r\n const body = {\r\n scope: validated.scope,\r\n acting_for: validated.actingFor,\r\n ttl_seconds: validated.ttlSeconds ?? 60,\r\n };\r\n const data = await this.post<{\r\n token: string;\r\n token_id: string;\r\n expires_at: number;\r\n }>(\"/v1/tokens/mint\", body);\r\n\r\n return {\r\n token: data.token,\r\n tokenId: data.token_id,\r\n expiresAt: new Date(data.expires_at * 1000),\r\n };\r\n }\r\n\r\n // ── Token revocation ───────────────────────────────────────────────────────\r\n\r\n /**\r\n * Immediately revokes a JIT token by its ID.\r\n */\r\n async revokeToken(tokenId: string): Promise<RevokeTokenResult> {\r\n const data = await this.delete<{ success: boolean }>(\r\n `/v1/tokens/${encodeURIComponent(tokenId)}`\r\n );\r\n return { success: data.success };\r\n }\r\n\r\n // ── Multi-agent delegation ─────────────────────────────────────────────────\r\n\r\n /**\r\n * Delegates a constrained sub-scope from one agent to another.\r\n *\r\n * Validates the delegation rule in the loaded policy, caps the TTL to the\r\n * policy maximum, and mints a child JIT token scoped to the granted actions.\r\n *\r\n * The delegator's `confidence` score is checked against the policy's\r\n * `require_confidence_above` before delegation is granted.\r\n */\r\n async delegateScope(req: DelegateScopeRequest): Promise<DelegateScopeResult> {\r\n const validated = DelegateScopeRequestSchema.parse(req);\r\n const body = {\r\n delegator: validated.delegator,\r\n delegatee: validated.delegatee,\r\n scoped_to: validated.scopedTo ?? [],\r\n ttl_seconds: validated.ttlSeconds ?? 60,\r\n confidence: validated.confidence ?? 1.0,\r\n acting_for: validated.actingFor ?? \"\",\r\n tenant_id: validated.tenantId ?? \"\",\r\n };\r\n const data = await this.post<{\r\n token: string;\r\n token_id: string;\r\n expires_at: number;\r\n delegator: string;\r\n delegatee: string;\r\n granted_scopes: string[];\r\n trace_id: string;\r\n }>(\"/v1/agent/delegate\", body);\r\n\r\n return {\r\n token: data.token,\r\n tokenId: data.token_id,\r\n expiresAt: new Date(data.expires_at * 1000),\r\n delegator: data.delegator,\r\n delegatee: data.delegatee,\r\n grantedScopes: data.granted_scopes,\r\n traceId: data.trace_id,\r\n };\r\n }\r\n\r\n // ── Health check ───────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Returns true if the engine is reachable and healthy.\r\n */\r\n async isHealthy(): Promise<boolean> {\r\n try {\r\n const data = await this.get<{ status: string }>(\"/healthz\");\r\n return data.status === \"ok\";\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n // ── HTTP helpers ───────────────────────────────────────────────────────────\r\n\r\n private headers(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (this.apiKey) {\r\n h[\"Authorization\"] = `Bearer ${this.apiKey}`;\r\n }\r\n return h;\r\n }\r\n\r\n private async post<T>(path: string, body: unknown): Promise<T> {\r\n const ctrl = new AbortController();\r\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method: \"POST\",\r\n headers: this.headers(),\r\n body: JSON.stringify(body),\r\n signal: ctrl.signal,\r\n });\r\n return this.parseResponse<T>(res);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n\r\n private async delete<T>(path: string): Promise<T> {\r\n const ctrl = new AbortController();\r\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method: \"DELETE\",\r\n headers: this.headers(),\r\n signal: ctrl.signal,\r\n });\r\n return this.parseResponse<T>(res);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n\r\n private async get<T>(path: string): Promise<T> {\r\n const ctrl = new AbortController();\r\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method: \"GET\",\r\n headers: this.headers(),\r\n signal: ctrl.signal,\r\n });\r\n return this.parseResponse<T>(res);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n\r\n private async parseResponse<T>(res: Response): Promise<T> {\r\n const json = (await res.json()) as Record<string, unknown>;\r\n if (!res.ok) {\r\n throw new AuthEngineError(\r\n (json[\"error\"] as string) ?? \"engine error\",\r\n res.status,\r\n json\r\n );\r\n }\r\n return json as T;\r\n }\r\n}\r\n","import type { Request, Response, NextFunction, RequestHandler } from \"express\";\r\nimport { LeluClient } from \"../client\";\r\n\r\nexport interface AuthorizeOptions {\r\n /** Base URL of the Lelu engine (default: http://localhost:8080) */\r\n baseUrl?: string;\r\n /** API key for the Lelu engine */\r\n apiKey?: string;\r\n /** HTTP header that carries the actor identifier (default: x-actor) */\r\n actorHeader?: string;\r\n /** Confidence score to pass to the engine (default: 1.0) */\r\n confidence?: number;\r\n /** Explicit LeluClient instance (overrides baseUrl/apiKey) */\r\n client?: LeluClient;\r\n}\r\n\r\n/**\r\n * Express middleware factory that calls the Lelu engine and either calls\r\n * `next()` (allowed) or returns a 403 JSON response (denied / human_review).\r\n *\r\n * ```ts\r\n * import express from \"express\";\r\n * import { authorize } from \"@lelu/sdk/express\";\r\n *\r\n * const app = express();\r\n * app.get(\"/sensitive\", authorize(\"files.read\", { confidence: 0.9 }), handler);\r\n * ```\r\n */\r\nexport function authorize(action: string, opts: AuthorizeOptions = {}): RequestHandler {\r\n const clientConfig: any = {\r\n baseUrl: opts.baseUrl ?? process.env[\"LELU_BASE_URL\"] ?? \"http://localhost:8080\",\r\n };\r\n const apiKey = opts.apiKey ?? process.env[\"LELU_API_KEY\"];\r\n if (apiKey !== undefined) {\r\n clientConfig.apiKey = apiKey;\r\n }\r\n const client = opts.client ?? new LeluClient(clientConfig);\r\n\r\n const actorHeader = opts.actorHeader ?? \"x-actor\";\r\n const confidence = opts.confidence ?? 1.0;\r\n\r\n return async function leluAuthorize(\r\n req: Request,\r\n res: Response,\r\n next: NextFunction\r\n ): Promise<void> {\r\n const actor = (req.headers[actorHeader] as string | undefined) ?? \"anonymous\";\r\n\r\n try {\r\n const decision = await client.agentAuthorize({ actor, action, context: { confidence } });\r\n\r\n if (decision.allowed) {\r\n // Attach decision to request for downstream handlers\r\n (req as Request & { leluDecision: typeof decision }).leluDecision = decision;\r\n next();\r\n return;\r\n }\r\n\r\n res.status(403).json({\r\n error: \"forbidden\",\r\n decision: decision.allowed,\r\n reason: decision.reason ?? \"denied by policy\",\r\n actor,\r\n action,\r\n });\r\n } catch (err) {\r\n res.status(503).json({\r\n error: \"lelu_unavailable\",\r\n message: err instanceof Error ? err.message : String(err),\r\n });\r\n }\r\n };\r\n}\r\n"]}
1
+ {"version":3,"sources":["../../src/types.ts","../../src/client.ts","../../src/express/index.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from \"zod\";\n\n// ─── Request / Response schemas ───────────────────────────────────────────────\n\nexport const AuthRequestSchema = z.object({\n userId: z.string().min(1, \"userId is required\"),\n action: z.string().min(1, \"action is required\"),\n resource: z.record(z.string()).optional(),\n});\n\nexport const AgentContextSchema = z.object({\n /** LLM confidence score — 0.0 to 1.0 */\n confidence: z.number().min(0).max(1),\n /** User the agent is acting on behalf of */\n actingFor: z.string().optional(),\n /** Requested agent scope */\n scope: z.string().optional(),\n});\n\nexport const AgentAuthRequestSchema = z.object({\n actor: z.string().min(1, \"actor is required\"),\n action: z.string().min(1, \"action is required\"),\n resource: z.record(z.string()).optional(),\n context: AgentContextSchema,\n});\n\nexport const MintTokenRequestSchema = z.object({\n scope: z.string().min(1),\n actingFor: z.string().optional(),\n ttlSeconds: z.number().int().positive().optional(),\n});\n\nexport const DelegateScopeRequestSchema = z.object({\n delegator: z.string().min(1, \"delegator is required\"),\n delegatee: z.string().min(1, \"delegatee is required\"),\n scopedTo: z.array(z.string().min(1)).optional(),\n ttlSeconds: z.number().int().positive().optional(),\n confidence: z.number().min(0).max(1).optional(),\n actingFor: z.string().optional(),\n tenantId: z.string().optional(),\n});\n\n// ─── Decision types ───────────────────────────────────────────────────────────\n\nexport interface AuthDecision {\n allowed: boolean;\n reason: string;\n traceId: string;\n}\n\nexport interface AgentAuthDecision {\n allowed: boolean;\n reason: string;\n traceId: string;\n downgradedScope: string | undefined;\n requiresHumanReview: boolean;\n confidenceUsed: number;\n}\n\nexport interface MintTokenResult {\n token: string;\n tokenId: string;\n expiresAt: Date;\n}\n\nexport interface DelegateScopeRequest {\n /** Agent delegating the scope */\n delegator: string;\n /** Agent receiving the constrained sub-scope */\n delegatee: string;\n /** Actions to grant (must be subset of policy's can_delegate.scoped_to) */\n scopedTo?: string[];\n /** Token TTL in seconds — capped by the policy's max_ttl_seconds */\n ttlSeconds?: number;\n /** Delegator's confidence score — checked against require_confidence_above */\n confidence?: number;\n /** User the delegated agent acts on behalf of */\n actingFor?: string;\n tenantId?: string;\n}\n\nexport interface DelegateScopeResult {\n token: string;\n tokenId: string;\n expiresAt: Date;\n delegator: string;\n delegatee: string;\n grantedScopes: string[];\n traceId: string;\n}\n\nexport interface RevokeTokenResult {\n success: boolean;\n}\n\n// ─── Typed Input types ───────────────────────────────────────────────────────\n\nexport type AuthRequest = z.infer<typeof AuthRequestSchema>;\nexport type AgentAuthRequest = z.infer<typeof AgentAuthRequestSchema>;\nexport type AgentContext = z.infer<typeof AgentContextSchema>;\nexport type MintTokenRequest = z.infer<typeof MintTokenRequestSchema>;\n\n// ─── Client config ────────────────────────────────────────────────────────────\n\nexport interface ClientConfig {\n /** Base URL of the Auth Permission Engine (default: http://localhost:8080) */\n baseUrl?: string;\n /** Request timeout in milliseconds (default: 5000) */\n timeoutMs?: number;\n /** Optional bearer token for authenticating with the engine */\n apiKey?: string;\n}\n\n// ─── Error type ───────────────────────────────────────────────────────────────\n\nexport class AuthEngineError extends Error {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly details?: unknown\n ) {\n super(message);\n this.name = \"AuthEngineError\";\n }\n}\n","import {\n AuthEngineError,\n AuthRequestSchema,\n AgentAuthRequestSchema,\n MintTokenRequestSchema,\n DelegateScopeRequestSchema,\n type AuthDecision,\n type AgentAuthDecision,\n type MintTokenResult,\n type DelegateScopeResult,\n type DelegateScopeRequest,\n type RevokeTokenResult,\n type AuthRequest,\n type AgentAuthRequest,\n type MintTokenRequest,\n type ClientConfig,\n} from \"./types.js\";\n\n// ─── Client ───────────────────────────────────────────────────────────────────\n\n/**\n * LeluClient is the core SDK entry-point. It communicates with the local\n * Auth Permission Engine sidecar over HTTP/JSON.\n *\n * @example\n * ```ts\n * const lelu = new LeluClient({ baseUrl: \"http://localhost:8080\" });\n *\n * const decision = await lelu.agentAuthorize({\n * actor: \"invoice_bot\",\n * action: \"approve_refunds\",\n * context: { confidence: 0.92, actingFor: \"user_123\" },\n * });\n *\n * if (!decision.allowed) {\n * console.log(decision.reason);\n * }\n * ```\n */\nexport class LeluClient {\n private readonly baseUrl: string;\n private readonly timeoutMs: number;\n private readonly apiKey: string | undefined;\n\n constructor(cfg: ClientConfig = {}) {\n this.baseUrl = (cfg.baseUrl ?? \"http://localhost:8080\").replace(/\\/$/, \"\");\n this.timeoutMs = cfg.timeoutMs ?? 5_000;\n this.apiKey = cfg.apiKey;\n }\n\n // ── Human authorization ────────────────────────────────────────────────────\n\n /**\n * Checks whether a human user is permitted to perform an action.\n */\n async authorize(req: AuthRequest): Promise<AuthDecision> {\n const validated = AuthRequestSchema.parse(req);\n const body = {\n user_id: validated.userId,\n action: validated.action,\n resource: validated.resource,\n };\n const data = await this.post<{\n allowed: boolean;\n reason: string;\n trace_id: string;\n }>(\"/v1/authorize\", body);\n\n return {\n allowed: data.allowed,\n reason: data.reason,\n traceId: data.trace_id,\n };\n }\n\n // ── Agent authorization ────────────────────────────────────────────────────\n\n /**\n * Checks whether an AI agent is permitted to perform an action, taking the\n * confidence score into account (Confidence-Aware Auth ★).\n */\n async agentAuthorize(req: AgentAuthRequest): Promise<AgentAuthDecision> {\n const validated = AgentAuthRequestSchema.parse(req);\n const body = {\n actor: validated.actor,\n action: validated.action,\n resource: validated.resource,\n confidence: validated.context.confidence,\n acting_for: validated.context.actingFor,\n scope: validated.context.scope,\n };\n const data = await this.post<{\n allowed: boolean;\n reason: string;\n trace_id: string;\n downgraded_scope?: string;\n requires_human_review: boolean;\n confidence_used: number;\n }>(\"/v1/agent/authorize\", body);\n\n return {\n allowed: data.allowed,\n reason: data.reason,\n traceId: data.trace_id,\n downgradedScope: data.downgraded_scope,\n requiresHumanReview: data.requires_human_review,\n confidenceUsed: data.confidence_used,\n };\n }\n\n // ── JIT Token minting ──────────────────────────────────────────────────────\n\n /**\n * Mints a scoped JWT for an agent with an optional TTL.\n * Default TTL is 60 seconds.\n */\n async mintToken(req: MintTokenRequest): Promise<MintTokenResult> {\n const validated = MintTokenRequestSchema.parse(req);\n const body = {\n scope: validated.scope,\n acting_for: validated.actingFor,\n ttl_seconds: validated.ttlSeconds ?? 60,\n };\n const data = await this.post<{\n token: string;\n token_id: string;\n expires_at: number;\n }>(\"/v1/tokens/mint\", body);\n\n return {\n token: data.token,\n tokenId: data.token_id,\n expiresAt: new Date(data.expires_at * 1000),\n };\n }\n\n // ── Token revocation ───────────────────────────────────────────────────────\n\n /**\n * Immediately revokes a JIT token by its ID.\n */\n async revokeToken(tokenId: string): Promise<RevokeTokenResult> {\n const data = await this.delete<{ success: boolean }>(\n `/v1/tokens/${encodeURIComponent(tokenId)}`\n );\n return { success: data.success };\n }\n\n // ── Multi-agent delegation ─────────────────────────────────────────────────\n\n /**\n * Delegates a constrained sub-scope from one agent to another.\n *\n * Validates the delegation rule in the loaded policy, caps the TTL to the\n * policy maximum, and mints a child JIT token scoped to the granted actions.\n *\n * The delegator's `confidence` score is checked against the policy's\n * `require_confidence_above` before delegation is granted.\n */\n async delegateScope(req: DelegateScopeRequest): Promise<DelegateScopeResult> {\n const validated = DelegateScopeRequestSchema.parse(req);\n const body = {\n delegator: validated.delegator,\n delegatee: validated.delegatee,\n scoped_to: validated.scopedTo ?? [],\n ttl_seconds: validated.ttlSeconds ?? 60,\n confidence: validated.confidence ?? 1.0,\n acting_for: validated.actingFor ?? \"\",\n tenant_id: validated.tenantId ?? \"\",\n };\n const data = await this.post<{\n token: string;\n token_id: string;\n expires_at: number;\n delegator: string;\n delegatee: string;\n granted_scopes: string[];\n trace_id: string;\n }>(\"/v1/agent/delegate\", body);\n\n return {\n token: data.token,\n tokenId: data.token_id,\n expiresAt: new Date(data.expires_at * 1000),\n delegator: data.delegator,\n delegatee: data.delegatee,\n grantedScopes: data.granted_scopes,\n traceId: data.trace_id,\n };\n }\n\n // ── Health check ───────────────────────────────────────────────────────────\n\n /**\n * Returns true if the engine is reachable and healthy.\n */\n async isHealthy(): Promise<boolean> {\n try {\n const data = await this.get<{ status: string }>(\"/healthz\");\n return data.status === \"ok\";\n } catch {\n return false;\n }\n }\n\n // ── HTTP helpers ───────────────────────────────────────────────────────────\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.apiKey) {\n h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n return h;\n }\n\n private async post<T>(path: string, body: unknown): Promise<T> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify(body),\n signal: ctrl.signal,\n });\n return this.parseResponse<T>(res);\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async delete<T>(path: string): Promise<T> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"DELETE\",\n headers: this.headers(),\n signal: ctrl.signal,\n });\n return this.parseResponse<T>(res);\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async get<T>(path: string): Promise<T> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"GET\",\n headers: this.headers(),\n signal: ctrl.signal,\n });\n return this.parseResponse<T>(res);\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async parseResponse<T>(res: Response): Promise<T> {\n const json = (await res.json()) as Record<string, unknown>;\n if (!res.ok) {\n throw new AuthEngineError(\n (json[\"error\"] as string) ?? \"engine error\",\n res.status,\n json\n );\n }\n return json as T;\n }\n}\n","import type { Request, Response, NextFunction, RequestHandler } from \"express\";\nimport { LeluClient } from \"../client\";\n\nexport interface AuthorizeOptions {\n /** Base URL of the Lelu engine (default: http://localhost:8080) */\n baseUrl?: string;\n /** API key for the Lelu engine */\n apiKey?: string;\n /** HTTP header that carries the actor identifier (default: x-actor) */\n actorHeader?: string;\n /** Confidence score to pass to the engine (default: 1.0) */\n confidence?: number;\n /** Explicit LeluClient instance (overrides baseUrl/apiKey) */\n client?: LeluClient;\n}\n\n/**\n * Express middleware factory that calls the Lelu engine and either calls\n * `next()` (allowed) or returns a 403 JSON response (denied / human_review).\n *\n * ```ts\n * import express from \"express\";\n * import { authorize } from \"@lelu/sdk/express\";\n *\n * const app = express();\n * app.get(\"/sensitive\", authorize(\"files.read\", { confidence: 0.9 }), handler);\n * ```\n */\nexport function authorize(action: string, opts: AuthorizeOptions = {}): RequestHandler {\n const clientConfig: any = {\n baseUrl: opts.baseUrl ?? process.env[\"LELU_BASE_URL\"] ?? \"http://localhost:8080\",\n };\n const apiKey = opts.apiKey ?? process.env[\"LELU_API_KEY\"];\n if (apiKey !== undefined) {\n clientConfig.apiKey = apiKey;\n }\n const client = opts.client ?? new LeluClient(clientConfig);\n\n const actorHeader = opts.actorHeader ?? \"x-actor\";\n const confidence = opts.confidence ?? 1.0;\n\n return async function leluAuthorize(\n req: Request,\n res: Response,\n next: NextFunction\n ): Promise<void> {\n const actor = (req.headers[actorHeader] as string | undefined) ?? \"anonymous\";\n\n try {\n const decision = await client.agentAuthorize({ actor, action, context: { confidence } });\n\n if (decision.allowed) {\n // Attach decision to request for downstream handlers\n (req as Request & { leluDecision: typeof decision }).leluDecision = decision;\n next();\n return;\n }\n\n res.status(403).json({\n error: \"forbidden\",\n decision: decision.allowed,\n reason: decision.reason ?? \"denied by policy\",\n actor,\n action,\n });\n } catch (err) {\n res.status(503).json({\n error: \"lelu_unavailable\",\n message: err instanceof Error ? err.message : String(err),\n });\n }\n };\n}\n"]}
@@ -49,8 +49,7 @@ var LeluClient = class {
49
49
  timeoutMs;
50
50
  apiKey;
51
51
  constructor(cfg = {}) {
52
- const envBaseUrl = typeof process !== "undefined" && process.env ? process.env["LELU_BASE_URL"] : void 0;
53
- this.baseUrl = (cfg.baseUrl ?? envBaseUrl ?? "http://localhost:8080").replace(/\/$/, "");
52
+ this.baseUrl = (cfg.baseUrl ?? "http://localhost:8080").replace(/\/$/, "");
54
53
  this.timeoutMs = cfg.timeoutMs ?? 5e3;
55
54
  this.apiKey = cfg.apiKey;
56
55
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types.ts","../../src/client.ts","../../src/express/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { z } from \"zod\";\r\n\r\n// ─── Request / Response schemas ───────────────────────────────────────────────\r\n\r\nexport const AuthRequestSchema = z.object({\r\n userId: z.string().min(1, \"userId is required\"),\r\n action: z.string().min(1, \"action is required\"),\r\n resource: z.record(z.string()).optional(),\r\n});\r\n\r\nexport const AgentContextSchema = z.object({\r\n /** LLM confidence score — 0.0 to 1.0 */\r\n confidence: z.number().min(0).max(1),\r\n /** User the agent is acting on behalf of */\r\n actingFor: z.string().optional(),\r\n /** Requested agent scope */\r\n scope: z.string().optional(),\r\n});\r\n\r\nexport const AgentAuthRequestSchema = z.object({\r\n actor: z.string().min(1, \"actor is required\"),\r\n action: z.string().min(1, \"action is required\"),\r\n resource: z.record(z.string()).optional(),\r\n context: AgentContextSchema,\r\n});\r\n\r\nexport const MintTokenRequestSchema = z.object({\r\n scope: z.string().min(1),\r\n actingFor: z.string().optional(),\r\n ttlSeconds: z.number().int().positive().optional(),\r\n});\r\n\r\nexport const DelegateScopeRequestSchema = z.object({\r\n delegator: z.string().min(1, \"delegator is required\"),\r\n delegatee: z.string().min(1, \"delegatee is required\"),\r\n scopedTo: z.array(z.string().min(1)).optional(),\r\n ttlSeconds: z.number().int().positive().optional(),\r\n confidence: z.number().min(0).max(1).optional(),\r\n actingFor: z.string().optional(),\r\n tenantId: z.string().optional(),\r\n});\r\n\r\n// ─── Decision types ───────────────────────────────────────────────────────────\r\n\r\nexport interface AuthDecision {\r\n allowed: boolean;\r\n reason: string;\r\n traceId: string;\r\n}\r\n\r\nexport interface AgentAuthDecision {\r\n allowed: boolean;\r\n reason: string;\r\n traceId: string;\r\n downgradedScope: string | undefined;\r\n requiresHumanReview: boolean;\r\n confidenceUsed: number;\r\n}\r\n\r\nexport interface MintTokenResult {\r\n token: string;\r\n tokenId: string;\r\n expiresAt: Date;\r\n}\r\n\r\nexport interface DelegateScopeRequest {\r\n /** Agent delegating the scope */\r\n delegator: string;\r\n /** Agent receiving the constrained sub-scope */\r\n delegatee: string;\r\n /** Actions to grant (must be subset of policy's can_delegate.scoped_to) */\r\n scopedTo?: string[];\r\n /** Token TTL in seconds — capped by the policy's max_ttl_seconds */\r\n ttlSeconds?: number;\r\n /** Delegator's confidence score — checked against require_confidence_above */\r\n confidence?: number;\r\n /** User the delegated agent acts on behalf of */\r\n actingFor?: string;\r\n tenantId?: string;\r\n}\r\n\r\nexport interface DelegateScopeResult {\r\n token: string;\r\n tokenId: string;\r\n expiresAt: Date;\r\n delegator: string;\r\n delegatee: string;\r\n grantedScopes: string[];\r\n traceId: string;\r\n}\r\n\r\nexport interface RevokeTokenResult {\r\n success: boolean;\r\n}\r\n\r\n// ─── Typed Input types ───────────────────────────────────────────────────────\r\n\r\nexport type AuthRequest = z.infer<typeof AuthRequestSchema>;\r\nexport type AgentAuthRequest = z.infer<typeof AgentAuthRequestSchema>;\r\nexport type AgentContext = z.infer<typeof AgentContextSchema>;\r\nexport type MintTokenRequest = z.infer<typeof MintTokenRequestSchema>;\r\n\r\n// ─── Client config ────────────────────────────────────────────────────────────\r\n\r\nexport interface ClientConfig {\r\n /** Base URL of the Auth Permission Engine (defaults to LELU_BASE_URL env var, else http://localhost:8080) */\r\n baseUrl?: string;\r\n /** Request timeout in milliseconds (default: 5000) */\r\n timeoutMs?: number;\r\n /** Optional bearer token for authenticating with the engine */\r\n apiKey?: string;\r\n}\r\n\r\n// ─── Error type ───────────────────────────────────────────────────────────────\r\n\r\nexport class AuthEngineError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly status?: number,\r\n public readonly details?: unknown\r\n ) {\r\n super(message);\r\n this.name = \"AuthEngineError\";\r\n }\r\n}\r\n","import {\r\n AuthEngineError,\r\n AuthRequestSchema,\r\n AgentAuthRequestSchema,\r\n MintTokenRequestSchema,\r\n DelegateScopeRequestSchema,\r\n type AuthDecision,\r\n type AgentAuthDecision,\r\n type MintTokenResult,\r\n type DelegateScopeResult,\r\n type DelegateScopeRequest,\r\n type RevokeTokenResult,\r\n type AuthRequest,\r\n type AgentAuthRequest,\r\n type MintTokenRequest,\r\n type ClientConfig,\r\n} from \"./types.js\";\r\n\r\n// ─── Client ───────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * LeluClient is the core SDK entry-point. It communicates with the local\r\n * Auth Permission Engine sidecar over HTTP/JSON.\r\n *\r\n * @example\r\n * ```ts\r\n * const lelu = new LeluClient({ baseUrl: \"http://localhost:8080\" });\r\n *\r\n * const decision = await lelu.agentAuthorize({\r\n * actor: \"invoice_bot\",\r\n * action: \"approve_refunds\",\r\n * context: { confidence: 0.92, actingFor: \"user_123\" },\r\n * });\r\n *\r\n * if (!decision.allowed) {\r\n * console.log(decision.reason);\r\n * }\r\n * ```\r\n */\r\nexport class LeluClient {\r\n private readonly baseUrl: string;\r\n private readonly timeoutMs: number;\r\n private readonly apiKey: string | undefined;\r\n\r\n constructor(cfg: ClientConfig = {}) {\r\n const envBaseUrl =\r\n typeof process !== \"undefined\" && process.env\r\n ? process.env[\"LELU_BASE_URL\"]\r\n : undefined;\r\n this.baseUrl = (cfg.baseUrl ?? envBaseUrl ?? \"http://localhost:8080\").replace(/\\/$/, \"\");\r\n this.timeoutMs = cfg.timeoutMs ?? 5_000;\r\n this.apiKey = cfg.apiKey;\r\n }\r\n\r\n // ── Human authorization ────────────────────────────────────────────────────\r\n\r\n /**\r\n * Checks whether a human user is permitted to perform an action.\r\n */\r\n async authorize(req: AuthRequest): Promise<AuthDecision> {\r\n const validated = AuthRequestSchema.parse(req);\r\n const body = {\r\n user_id: validated.userId,\r\n action: validated.action,\r\n resource: validated.resource,\r\n };\r\n const data = await this.post<{\r\n allowed: boolean;\r\n reason: string;\r\n trace_id: string;\r\n }>(\"/v1/authorize\", body);\r\n\r\n return {\r\n allowed: data.allowed,\r\n reason: data.reason,\r\n traceId: data.trace_id,\r\n };\r\n }\r\n\r\n // ── Agent authorization ────────────────────────────────────────────────────\r\n\r\n /**\r\n * Checks whether an AI agent is permitted to perform an action, taking the\r\n * confidence score into account (Confidence-Aware Auth ★).\r\n */\r\n async agentAuthorize(req: AgentAuthRequest): Promise<AgentAuthDecision> {\r\n const validated = AgentAuthRequestSchema.parse(req);\r\n const body = {\r\n actor: validated.actor,\r\n action: validated.action,\r\n resource: validated.resource,\r\n confidence: validated.context.confidence,\r\n acting_for: validated.context.actingFor,\r\n scope: validated.context.scope,\r\n };\r\n const data = await this.post<{\r\n allowed: boolean;\r\n reason: string;\r\n trace_id: string;\r\n downgraded_scope?: string;\r\n requires_human_review: boolean;\r\n confidence_used: number;\r\n }>(\"/v1/agent/authorize\", body);\r\n\r\n return {\r\n allowed: data.allowed,\r\n reason: data.reason,\r\n traceId: data.trace_id,\r\n downgradedScope: data.downgraded_scope,\r\n requiresHumanReview: data.requires_human_review,\r\n confidenceUsed: data.confidence_used,\r\n };\r\n }\r\n\r\n // ── JIT Token minting ──────────────────────────────────────────────────────\r\n\r\n /**\r\n * Mints a scoped JWT for an agent with an optional TTL.\r\n * Default TTL is 60 seconds.\r\n */\r\n async mintToken(req: MintTokenRequest): Promise<MintTokenResult> {\r\n const validated = MintTokenRequestSchema.parse(req);\r\n const body = {\r\n scope: validated.scope,\r\n acting_for: validated.actingFor,\r\n ttl_seconds: validated.ttlSeconds ?? 60,\r\n };\r\n const data = await this.post<{\r\n token: string;\r\n token_id: string;\r\n expires_at: number;\r\n }>(\"/v1/tokens/mint\", body);\r\n\r\n return {\r\n token: data.token,\r\n tokenId: data.token_id,\r\n expiresAt: new Date(data.expires_at * 1000),\r\n };\r\n }\r\n\r\n // ── Token revocation ───────────────────────────────────────────────────────\r\n\r\n /**\r\n * Immediately revokes a JIT token by its ID.\r\n */\r\n async revokeToken(tokenId: string): Promise<RevokeTokenResult> {\r\n const data = await this.delete<{ success: boolean }>(\r\n `/v1/tokens/${encodeURIComponent(tokenId)}`\r\n );\r\n return { success: data.success };\r\n }\r\n\r\n // ── Multi-agent delegation ─────────────────────────────────────────────────\r\n\r\n /**\r\n * Delegates a constrained sub-scope from one agent to another.\r\n *\r\n * Validates the delegation rule in the loaded policy, caps the TTL to the\r\n * policy maximum, and mints a child JIT token scoped to the granted actions.\r\n *\r\n * The delegator's `confidence` score is checked against the policy's\r\n * `require_confidence_above` before delegation is granted.\r\n */\r\n async delegateScope(req: DelegateScopeRequest): Promise<DelegateScopeResult> {\r\n const validated = DelegateScopeRequestSchema.parse(req);\r\n const body = {\r\n delegator: validated.delegator,\r\n delegatee: validated.delegatee,\r\n scoped_to: validated.scopedTo ?? [],\r\n ttl_seconds: validated.ttlSeconds ?? 60,\r\n confidence: validated.confidence ?? 1.0,\r\n acting_for: validated.actingFor ?? \"\",\r\n tenant_id: validated.tenantId ?? \"\",\r\n };\r\n const data = await this.post<{\r\n token: string;\r\n token_id: string;\r\n expires_at: number;\r\n delegator: string;\r\n delegatee: string;\r\n granted_scopes: string[];\r\n trace_id: string;\r\n }>(\"/v1/agent/delegate\", body);\r\n\r\n return {\r\n token: data.token,\r\n tokenId: data.token_id,\r\n expiresAt: new Date(data.expires_at * 1000),\r\n delegator: data.delegator,\r\n delegatee: data.delegatee,\r\n grantedScopes: data.granted_scopes,\r\n traceId: data.trace_id,\r\n };\r\n }\r\n\r\n // ── Health check ───────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Returns true if the engine is reachable and healthy.\r\n */\r\n async isHealthy(): Promise<boolean> {\r\n try {\r\n const data = await this.get<{ status: string }>(\"/healthz\");\r\n return data.status === \"ok\";\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n // ── HTTP helpers ───────────────────────────────────────────────────────────\r\n\r\n private headers(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (this.apiKey) {\r\n h[\"Authorization\"] = `Bearer ${this.apiKey}`;\r\n }\r\n return h;\r\n }\r\n\r\n private async post<T>(path: string, body: unknown): Promise<T> {\r\n const ctrl = new AbortController();\r\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method: \"POST\",\r\n headers: this.headers(),\r\n body: JSON.stringify(body),\r\n signal: ctrl.signal,\r\n });\r\n return this.parseResponse<T>(res);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n\r\n private async delete<T>(path: string): Promise<T> {\r\n const ctrl = new AbortController();\r\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method: \"DELETE\",\r\n headers: this.headers(),\r\n signal: ctrl.signal,\r\n });\r\n return this.parseResponse<T>(res);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n\r\n private async get<T>(path: string): Promise<T> {\r\n const ctrl = new AbortController();\r\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method: \"GET\",\r\n headers: this.headers(),\r\n signal: ctrl.signal,\r\n });\r\n return this.parseResponse<T>(res);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n\r\n private async parseResponse<T>(res: Response): Promise<T> {\r\n const json = (await res.json()) as Record<string, unknown>;\r\n if (!res.ok) {\r\n throw new AuthEngineError(\r\n (json[\"error\"] as string) ?? \"engine error\",\r\n res.status,\r\n json\r\n );\r\n }\r\n return json as T;\r\n }\r\n}\r\n","import type { Request, Response, NextFunction, RequestHandler } from \"express\";\r\nimport { LeluClient } from \"../client\";\r\n\r\nexport interface AuthorizeOptions {\r\n /** Base URL of the Lelu engine (default: http://localhost:8080) */\r\n baseUrl?: string;\r\n /** API key for the Lelu engine */\r\n apiKey?: string;\r\n /** HTTP header that carries the actor identifier (default: x-actor) */\r\n actorHeader?: string;\r\n /** Confidence score to pass to the engine (default: 1.0) */\r\n confidence?: number;\r\n /** Explicit LeluClient instance (overrides baseUrl/apiKey) */\r\n client?: LeluClient;\r\n}\r\n\r\n/**\r\n * Express middleware factory that calls the Lelu engine and either calls\r\n * `next()` (allowed) or returns a 403 JSON response (denied / human_review).\r\n *\r\n * ```ts\r\n * import express from \"express\";\r\n * import { authorize } from \"@lelu/sdk/express\";\r\n *\r\n * const app = express();\r\n * app.get(\"/sensitive\", authorize(\"files.read\", { confidence: 0.9 }), handler);\r\n * ```\r\n */\r\nexport function authorize(action: string, opts: AuthorizeOptions = {}): RequestHandler {\r\n const clientConfig: any = {\r\n baseUrl: opts.baseUrl ?? process.env[\"LELU_BASE_URL\"] ?? \"http://localhost:8080\",\r\n };\r\n const apiKey = opts.apiKey ?? process.env[\"LELU_API_KEY\"];\r\n if (apiKey !== undefined) {\r\n clientConfig.apiKey = apiKey;\r\n }\r\n const client = opts.client ?? new LeluClient(clientConfig);\r\n\r\n const actorHeader = opts.actorHeader ?? \"x-actor\";\r\n const confidence = opts.confidence ?? 1.0;\r\n\r\n return async function leluAuthorize(\r\n req: Request,\r\n res: Response,\r\n next: NextFunction\r\n ): Promise<void> {\r\n const actor = (req.headers[actorHeader] as string | undefined) ?? \"anonymous\";\r\n\r\n try {\r\n const decision = await client.agentAuthorize({ actor, action, context: { confidence } });\r\n\r\n if (decision.allowed) {\r\n // Attach decision to request for downstream handlers\r\n (req as Request & { leluDecision: typeof decision }).leluDecision = decision;\r\n next();\r\n return;\r\n }\r\n\r\n res.status(403).json({\r\n error: \"forbidden\",\r\n decision: decision.allowed,\r\n reason: decision.reason ?? \"denied by policy\",\r\n actor,\r\n action,\r\n });\r\n } catch (err) {\r\n res.status(503).json({\r\n error: \"lelu_unavailable\",\r\n message: err instanceof Error ? err.message : String(err),\r\n });\r\n }\r\n };\r\n}\r\n"]}
1
+ {"version":3,"sources":["../../src/types.ts","../../src/client.ts","../../src/express/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { z } from \"zod\";\n\n// ─── Request / Response schemas ───────────────────────────────────────────────\n\nexport const AuthRequestSchema = z.object({\n userId: z.string().min(1, \"userId is required\"),\n action: z.string().min(1, \"action is required\"),\n resource: z.record(z.string()).optional(),\n});\n\nexport const AgentContextSchema = z.object({\n /** LLM confidence score — 0.0 to 1.0 */\n confidence: z.number().min(0).max(1),\n /** User the agent is acting on behalf of */\n actingFor: z.string().optional(),\n /** Requested agent scope */\n scope: z.string().optional(),\n});\n\nexport const AgentAuthRequestSchema = z.object({\n actor: z.string().min(1, \"actor is required\"),\n action: z.string().min(1, \"action is required\"),\n resource: z.record(z.string()).optional(),\n context: AgentContextSchema,\n});\n\nexport const MintTokenRequestSchema = z.object({\n scope: z.string().min(1),\n actingFor: z.string().optional(),\n ttlSeconds: z.number().int().positive().optional(),\n});\n\nexport const DelegateScopeRequestSchema = z.object({\n delegator: z.string().min(1, \"delegator is required\"),\n delegatee: z.string().min(1, \"delegatee is required\"),\n scopedTo: z.array(z.string().min(1)).optional(),\n ttlSeconds: z.number().int().positive().optional(),\n confidence: z.number().min(0).max(1).optional(),\n actingFor: z.string().optional(),\n tenantId: z.string().optional(),\n});\n\n// ─── Decision types ───────────────────────────────────────────────────────────\n\nexport interface AuthDecision {\n allowed: boolean;\n reason: string;\n traceId: string;\n}\n\nexport interface AgentAuthDecision {\n allowed: boolean;\n reason: string;\n traceId: string;\n downgradedScope: string | undefined;\n requiresHumanReview: boolean;\n confidenceUsed: number;\n}\n\nexport interface MintTokenResult {\n token: string;\n tokenId: string;\n expiresAt: Date;\n}\n\nexport interface DelegateScopeRequest {\n /** Agent delegating the scope */\n delegator: string;\n /** Agent receiving the constrained sub-scope */\n delegatee: string;\n /** Actions to grant (must be subset of policy's can_delegate.scoped_to) */\n scopedTo?: string[];\n /** Token TTL in seconds — capped by the policy's max_ttl_seconds */\n ttlSeconds?: number;\n /** Delegator's confidence score — checked against require_confidence_above */\n confidence?: number;\n /** User the delegated agent acts on behalf of */\n actingFor?: string;\n tenantId?: string;\n}\n\nexport interface DelegateScopeResult {\n token: string;\n tokenId: string;\n expiresAt: Date;\n delegator: string;\n delegatee: string;\n grantedScopes: string[];\n traceId: string;\n}\n\nexport interface RevokeTokenResult {\n success: boolean;\n}\n\n// ─── Typed Input types ───────────────────────────────────────────────────────\n\nexport type AuthRequest = z.infer<typeof AuthRequestSchema>;\nexport type AgentAuthRequest = z.infer<typeof AgentAuthRequestSchema>;\nexport type AgentContext = z.infer<typeof AgentContextSchema>;\nexport type MintTokenRequest = z.infer<typeof MintTokenRequestSchema>;\n\n// ─── Client config ────────────────────────────────────────────────────────────\n\nexport interface ClientConfig {\n /** Base URL of the Auth Permission Engine (default: http://localhost:8080) */\n baseUrl?: string;\n /** Request timeout in milliseconds (default: 5000) */\n timeoutMs?: number;\n /** Optional bearer token for authenticating with the engine */\n apiKey?: string;\n}\n\n// ─── Error type ───────────────────────────────────────────────────────────────\n\nexport class AuthEngineError extends Error {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly details?: unknown\n ) {\n super(message);\n this.name = \"AuthEngineError\";\n }\n}\n","import {\n AuthEngineError,\n AuthRequestSchema,\n AgentAuthRequestSchema,\n MintTokenRequestSchema,\n DelegateScopeRequestSchema,\n type AuthDecision,\n type AgentAuthDecision,\n type MintTokenResult,\n type DelegateScopeResult,\n type DelegateScopeRequest,\n type RevokeTokenResult,\n type AuthRequest,\n type AgentAuthRequest,\n type MintTokenRequest,\n type ClientConfig,\n} from \"./types.js\";\n\n// ─── Client ───────────────────────────────────────────────────────────────────\n\n/**\n * LeluClient is the core SDK entry-point. It communicates with the local\n * Auth Permission Engine sidecar over HTTP/JSON.\n *\n * @example\n * ```ts\n * const lelu = new LeluClient({ baseUrl: \"http://localhost:8080\" });\n *\n * const decision = await lelu.agentAuthorize({\n * actor: \"invoice_bot\",\n * action: \"approve_refunds\",\n * context: { confidence: 0.92, actingFor: \"user_123\" },\n * });\n *\n * if (!decision.allowed) {\n * console.log(decision.reason);\n * }\n * ```\n */\nexport class LeluClient {\n private readonly baseUrl: string;\n private readonly timeoutMs: number;\n private readonly apiKey: string | undefined;\n\n constructor(cfg: ClientConfig = {}) {\n this.baseUrl = (cfg.baseUrl ?? \"http://localhost:8080\").replace(/\\/$/, \"\");\n this.timeoutMs = cfg.timeoutMs ?? 5_000;\n this.apiKey = cfg.apiKey;\n }\n\n // ── Human authorization ────────────────────────────────────────────────────\n\n /**\n * Checks whether a human user is permitted to perform an action.\n */\n async authorize(req: AuthRequest): Promise<AuthDecision> {\n const validated = AuthRequestSchema.parse(req);\n const body = {\n user_id: validated.userId,\n action: validated.action,\n resource: validated.resource,\n };\n const data = await this.post<{\n allowed: boolean;\n reason: string;\n trace_id: string;\n }>(\"/v1/authorize\", body);\n\n return {\n allowed: data.allowed,\n reason: data.reason,\n traceId: data.trace_id,\n };\n }\n\n // ── Agent authorization ────────────────────────────────────────────────────\n\n /**\n * Checks whether an AI agent is permitted to perform an action, taking the\n * confidence score into account (Confidence-Aware Auth ★).\n */\n async agentAuthorize(req: AgentAuthRequest): Promise<AgentAuthDecision> {\n const validated = AgentAuthRequestSchema.parse(req);\n const body = {\n actor: validated.actor,\n action: validated.action,\n resource: validated.resource,\n confidence: validated.context.confidence,\n acting_for: validated.context.actingFor,\n scope: validated.context.scope,\n };\n const data = await this.post<{\n allowed: boolean;\n reason: string;\n trace_id: string;\n downgraded_scope?: string;\n requires_human_review: boolean;\n confidence_used: number;\n }>(\"/v1/agent/authorize\", body);\n\n return {\n allowed: data.allowed,\n reason: data.reason,\n traceId: data.trace_id,\n downgradedScope: data.downgraded_scope,\n requiresHumanReview: data.requires_human_review,\n confidenceUsed: data.confidence_used,\n };\n }\n\n // ── JIT Token minting ──────────────────────────────────────────────────────\n\n /**\n * Mints a scoped JWT for an agent with an optional TTL.\n * Default TTL is 60 seconds.\n */\n async mintToken(req: MintTokenRequest): Promise<MintTokenResult> {\n const validated = MintTokenRequestSchema.parse(req);\n const body = {\n scope: validated.scope,\n acting_for: validated.actingFor,\n ttl_seconds: validated.ttlSeconds ?? 60,\n };\n const data = await this.post<{\n token: string;\n token_id: string;\n expires_at: number;\n }>(\"/v1/tokens/mint\", body);\n\n return {\n token: data.token,\n tokenId: data.token_id,\n expiresAt: new Date(data.expires_at * 1000),\n };\n }\n\n // ── Token revocation ───────────────────────────────────────────────────────\n\n /**\n * Immediately revokes a JIT token by its ID.\n */\n async revokeToken(tokenId: string): Promise<RevokeTokenResult> {\n const data = await this.delete<{ success: boolean }>(\n `/v1/tokens/${encodeURIComponent(tokenId)}`\n );\n return { success: data.success };\n }\n\n // ── Multi-agent delegation ─────────────────────────────────────────────────\n\n /**\n * Delegates a constrained sub-scope from one agent to another.\n *\n * Validates the delegation rule in the loaded policy, caps the TTL to the\n * policy maximum, and mints a child JIT token scoped to the granted actions.\n *\n * The delegator's `confidence` score is checked against the policy's\n * `require_confidence_above` before delegation is granted.\n */\n async delegateScope(req: DelegateScopeRequest): Promise<DelegateScopeResult> {\n const validated = DelegateScopeRequestSchema.parse(req);\n const body = {\n delegator: validated.delegator,\n delegatee: validated.delegatee,\n scoped_to: validated.scopedTo ?? [],\n ttl_seconds: validated.ttlSeconds ?? 60,\n confidence: validated.confidence ?? 1.0,\n acting_for: validated.actingFor ?? \"\",\n tenant_id: validated.tenantId ?? \"\",\n };\n const data = await this.post<{\n token: string;\n token_id: string;\n expires_at: number;\n delegator: string;\n delegatee: string;\n granted_scopes: string[];\n trace_id: string;\n }>(\"/v1/agent/delegate\", body);\n\n return {\n token: data.token,\n tokenId: data.token_id,\n expiresAt: new Date(data.expires_at * 1000),\n delegator: data.delegator,\n delegatee: data.delegatee,\n grantedScopes: data.granted_scopes,\n traceId: data.trace_id,\n };\n }\n\n // ── Health check ───────────────────────────────────────────────────────────\n\n /**\n * Returns true if the engine is reachable and healthy.\n */\n async isHealthy(): Promise<boolean> {\n try {\n const data = await this.get<{ status: string }>(\"/healthz\");\n return data.status === \"ok\";\n } catch {\n return false;\n }\n }\n\n // ── HTTP helpers ───────────────────────────────────────────────────────────\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.apiKey) {\n h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n return h;\n }\n\n private async post<T>(path: string, body: unknown): Promise<T> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify(body),\n signal: ctrl.signal,\n });\n return this.parseResponse<T>(res);\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async delete<T>(path: string): Promise<T> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"DELETE\",\n headers: this.headers(),\n signal: ctrl.signal,\n });\n return this.parseResponse<T>(res);\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async get<T>(path: string): Promise<T> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n try {\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"GET\",\n headers: this.headers(),\n signal: ctrl.signal,\n });\n return this.parseResponse<T>(res);\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async parseResponse<T>(res: Response): Promise<T> {\n const json = (await res.json()) as Record<string, unknown>;\n if (!res.ok) {\n throw new AuthEngineError(\n (json[\"error\"] as string) ?? \"engine error\",\n res.status,\n json\n );\n }\n return json as T;\n }\n}\n","import type { Request, Response, NextFunction, RequestHandler } from \"express\";\nimport { LeluClient } from \"../client\";\n\nexport interface AuthorizeOptions {\n /** Base URL of the Lelu engine (default: http://localhost:8080) */\n baseUrl?: string;\n /** API key for the Lelu engine */\n apiKey?: string;\n /** HTTP header that carries the actor identifier (default: x-actor) */\n actorHeader?: string;\n /** Confidence score to pass to the engine (default: 1.0) */\n confidence?: number;\n /** Explicit LeluClient instance (overrides baseUrl/apiKey) */\n client?: LeluClient;\n}\n\n/**\n * Express middleware factory that calls the Lelu engine and either calls\n * `next()` (allowed) or returns a 403 JSON response (denied / human_review).\n *\n * ```ts\n * import express from \"express\";\n * import { authorize } from \"@lelu/sdk/express\";\n *\n * const app = express();\n * app.get(\"/sensitive\", authorize(\"files.read\", { confidence: 0.9 }), handler);\n * ```\n */\nexport function authorize(action: string, opts: AuthorizeOptions = {}): RequestHandler {\n const clientConfig: any = {\n baseUrl: opts.baseUrl ?? process.env[\"LELU_BASE_URL\"] ?? \"http://localhost:8080\",\n };\n const apiKey = opts.apiKey ?? process.env[\"LELU_API_KEY\"];\n if (apiKey !== undefined) {\n clientConfig.apiKey = apiKey;\n }\n const client = opts.client ?? new LeluClient(clientConfig);\n\n const actorHeader = opts.actorHeader ?? \"x-actor\";\n const confidence = opts.confidence ?? 1.0;\n\n return async function leluAuthorize(\n req: Request,\n res: Response,\n next: NextFunction\n ): Promise<void> {\n const actor = (req.headers[actorHeader] as string | undefined) ?? \"anonymous\";\n\n try {\n const decision = await client.agentAuthorize({ actor, action, context: { confidence } });\n\n if (decision.allowed) {\n // Attach decision to request for downstream handlers\n (req as Request & { leluDecision: typeof decision }).leluDecision = decision;\n next();\n return;\n }\n\n res.status(403).json({\n error: \"forbidden\",\n decision: decision.allowed,\n reason: decision.reason ?? \"denied by policy\",\n actor,\n action,\n });\n } catch (err) {\n res.status(503).json({\n error: \"lelu_unavailable\",\n message: err instanceof Error ? err.message : String(err),\n });\n }\n };\n}\n"]}
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { L as LeluClient, C as ClientConfig } from './client-DL75VVER.mjs';
2
- export { A as AgentAuthDecision, a as AgentAuthRequest, b as AgentAuthRequestSchema, c as AgentContext, d as AgentContextSchema, e as AuthDecision, f as AuthEngineError, g as AuthRequest, h as AuthRequestSchema, D as DelegateScopeRequest, i as DelegateScopeRequestSchema, j as DelegateScopeResult, M as MintTokenRequest, k as MintTokenRequestSchema, l as MintTokenResult, R as RevokeTokenResult } from './client-DL75VVER.mjs';
1
+ import { L as LeluClient, C as ClientConfig } from './client-BD9h8CBT.mjs';
2
+ export { A as AgentAuthDecision, a as AgentAuthRequest, b as AgentAuthRequestSchema, c as AgentContext, d as AgentContextSchema, e as AuthDecision, f as AuthEngineError, g as AuthRequest, h as AuthRequestSchema, D as DelegateScopeRequest, i as DelegateScopeRequestSchema, j as DelegateScopeResult, M as MintTokenRequest, k as MintTokenRequestSchema, l as MintTokenResult, R as RevokeTokenResult } from './client-BD9h8CBT.mjs';
3
3
  import 'zod';
4
4
 
5
5
  /**
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { L as LeluClient, C as ClientConfig } from './client-DL75VVER.js';
2
- export { A as AgentAuthDecision, a as AgentAuthRequest, b as AgentAuthRequestSchema, c as AgentContext, d as AgentContextSchema, e as AuthDecision, f as AuthEngineError, g as AuthRequest, h as AuthRequestSchema, D as DelegateScopeRequest, i as DelegateScopeRequestSchema, j as DelegateScopeResult, M as MintTokenRequest, k as MintTokenRequestSchema, l as MintTokenResult, R as RevokeTokenResult } from './client-DL75VVER.js';
1
+ import { L as LeluClient, C as ClientConfig } from './client-BD9h8CBT.js';
2
+ export { A as AgentAuthDecision, a as AgentAuthRequest, b as AgentAuthRequestSchema, c as AgentContext, d as AgentContextSchema, e as AuthDecision, f as AuthEngineError, g as AuthRequest, h as AuthRequestSchema, D as DelegateScopeRequest, i as DelegateScopeRequestSchema, j as DelegateScopeResult, M as MintTokenRequest, k as MintTokenRequestSchema, l as MintTokenResult, R as RevokeTokenResult } from './client-BD9h8CBT.js';
3
3
  import 'zod';
4
4
 
5
5
  /**
package/dist/index.js CHANGED
@@ -104,8 +104,7 @@ var LeluClient = class {
104
104
  timeoutMs;
105
105
  apiKey;
106
106
  constructor(cfg = {}) {
107
- const envBaseUrl = typeof process !== "undefined" && process.env ? process.env["LELU_BASE_URL"] : void 0;
108
- this.baseUrl = (cfg.baseUrl ?? envBaseUrl ?? "http://localhost:8080").replace(/\/$/, "");
107
+ this.baseUrl = (cfg.baseUrl ?? "http://localhost:8080").replace(/\/$/, "");
109
108
  this.timeoutMs = cfg.timeoutMs ?? 5e3;
110
109
  this.apiKey = cfg.apiKey;
111
110
  }