@lelu-auth/lelu 0.1.0 → 0.1.4
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 +21 -21
- package/README.md +96 -55
- package/dist/{client-BD9h8CBT.d.mts → client-DL75VVER.d.mts} +1 -1
- package/dist/{client-BD9h8CBT.d.ts → client-DL75VVER.d.ts} +1 -1
- package/dist/express/index.d.mts +1 -1
- package/dist/express/index.d.ts +1 -1
- package/dist/express/index.js +2 -1
- package/dist/express/index.js.map +1 -1
- package/dist/express/index.mjs +2 -1
- package/dist/express/index.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.d.mts +1 -1
- package/dist/langchain/index.d.ts +1 -1
- package/dist/langchain/index.js.map +1 -1
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/react/index.js +2 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +2 -1
- package/dist/react/index.mjs.map +1 -1
- package/package.json +99 -95
- package/scripts/lelu.js +97 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vercel/index.ts","../src/types.ts","../src/client.ts","../src/index.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Vercel AI SDK integration for Lelu — Confidence-Aware Auth.\n *\n * Wraps a Vercel AI SDK `tool()` definition with a Lelu authorization\n * gate. The wrapped tool runs the original `execute` function only when\n * Lelu allows it; otherwise it returns a structured refusal object that\n * the model can inspect and self-correct on.\n *\n * @example\n * ```ts\n * import { tool } from 'ai';\n * import { z } from 'zod';\n * import { LeluClient } from '@lelu-auth/lelu';\n * import { secureTool } from 'lelu/vercel';\n *\n * const lelu = new LeluClient({ baseUrl: 'http://localhost:8082' });\n *\n * const refundTool = secureTool({\n * client: lelu,\n * actor: 'invoice_bot',\n * action: 'invoice:refund',\n * confidence: 0.92,\n * tool: tool({\n * description: 'Process a customer refund',\n * parameters: z.object({ invoiceId: z.string() }),\n * execute: async ({ invoiceId }) => ({ refunded: invoiceId }),\n * }),\n * });\n *\n * // Use in streamText / generateText:\n * const result = await streamText({\n * model: openai('gpt-4o'),\n * tools: { refundTool },\n * });\n * ```\n */\n\nimport { LeluClient } from \"../client.js\";\n\n// ─── Minimal Vercel AI SDK tool type ──────────────────────────────────────────\n\n/**\n * The minimal shape of a Vercel AI SDK `tool()` return value.\n * We keep this local to avoid a hard dependency on `ai`.\n */\nexport interface VercelTool<TArgs = unknown, TResult = unknown> {\n description?: string;\n parameters: unknown;\n execute?: (args: TArgs, options?: unknown) => Promise<TResult>;\n}\n\n// ─── Denied / Review result shape ─────────────────────────────────────────────\n\nexport interface LeluDeniedResult {\n /** Always `false` when the tool was blocked. */\n allowed: false;\n /** Human/LLM-readable denial reason. */\n reason: string;\n /** Whether the action is queued for human review. */\n requiresHumanReview: boolean;\n /** The downgraded scope when confidence caused a downgrade. */\n downgradedScope?: string;\n}\n\n// ─── Options ──────────────────────────────────────────────────────────────────\n\nexport interface SecureToolOptions<TArgs = unknown, TResult = unknown> {\n /** Configured Lelu client. */\n client: LeluClient;\n /** The agent actor / scope registered in Lelu policy. */\n actor: string;\n /** The permission string being checked. */\n action: string;\n /**\n * LLM confidence score (0.0–1.0). Can be a static number or a function\n * receiving the parsed tool arguments, allowing dynamic confidence based\n * on the actual call. Defaults to `1.0`.\n */\n confidence?: number | ((args: TArgs) => number);\n /** Optional user ID the agent is acting on behalf of. */\n actingFor?: string;\n /** The original Vercel AI SDK tool to wrap. */\n tool: VercelTool<TArgs, TResult>;\n}\n\n// ─── secureTool ───────────────────────────────────────────────────────────────\n\n/**\n * Wraps a Vercel AI SDK `tool()` with Lelu Confidence-Aware Auth.\n *\n * Returns a new tool object with the same `description` and `parameters`\n * but with an `execute` function that gates through Lelu first.\n *\n * On denial the tool returns a `LeluDeniedResult` object (not a throw) so\n * the model sees a structured response it can reason about.\n */\nexport function secureTool<TArgs = unknown, TResult = unknown>(\n opts: SecureToolOptions<TArgs, TResult>\n): VercelTool<TArgs, TResult | LeluDeniedResult> {\n const { client, actor, action, actingFor } = opts;\n\n const wrapped: VercelTool<TArgs, TResult | LeluDeniedResult> = {\n parameters: opts.tool.parameters,\n\n async execute(\n args: TArgs,\n options?: unknown\n ): Promise<TResult | LeluDeniedResult> {\n // Resolve confidence — static number or dynamic function.\n const confidence =\n typeof opts.confidence === \"function\"\n ? opts.confidence(args)\n : (opts.confidence ?? 1.0);\n\n let decision;\n try {\n decision = await client.agentAuthorize({\n actor,\n action,\n context: { confidence, actingFor },\n });\n } catch (err) {\n // Fail open with a structured denial so the model can handle it.\n return {\n allowed: false,\n reason: `Lelu authorization check failed: ${String(err)}`,\n requiresHumanReview: false,\n };\n }\n\n // ── Human review required ──────────────────────────────────────────\n if (decision.requiresHumanReview) {\n return {\n allowed: false,\n reason:\n `Action '${action}' for agent '${actor}' is queued for human review. ` +\n `Reason: ${decision.reason}. Confidence: ${(confidence * 100).toFixed(0)}%.`,\n requiresHumanReview: true,\n };\n }\n\n // ── Hard deny ─────────────────────────────────────────────────────\n if (!decision.allowed) {\n const denied: LeluDeniedResult = {\n allowed: false,\n reason:\n `Action '${action}' was denied for agent '${actor}'. ` +\n `Reason: ${decision.reason}.`,\n requiresHumanReview: false,\n };\n if (decision.downgradedScope !== undefined) {\n denied.downgradedScope = decision.downgradedScope;\n }\n return {\n ...denied,\n };\n }\n\n // ── Authorized — run original execute ─────────────────────────────\n if (!opts.tool.execute) {\n throw new Error(\n `[Lelu] secureTool: the wrapped tool '${action}' has no execute function.`\n );\n }\n return opts.tool.execute(args, options);\n },\n };\n\n if (opts.tool.description !== undefined) {\n wrapped.description = opts.tool.description;\n }\n\n return wrapped;\n}\n","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","// Auth Permission Engine — TypeScript SDK\n// Public API surface\n\n// ─── Vercel AI SDK integration ────────────────────────────────────────────────\n// Import via: import { secureTool } from 'lelu/vercel'\n// (tree-shakeable — does not add weight to non-Vercel users)\nexport { secureTool } from \"./vercel/index.js\";\nexport type { SecureToolOptions, LeluDeniedResult, VercelTool } from \"./vercel/index.js\";\n\nexport { LeluClient } from \"./client.js\";\n\nexport type {\n AuthRequest,\n AgentAuthRequest,\n AgentContext,\n MintTokenRequest,\n DelegateScopeRequest,\n AuthDecision,\n AgentAuthDecision,\n MintTokenResult,\n DelegateScopeResult,\n RevokeTokenResult,\n ClientConfig,\n} from \"./types.js\";\n\nexport {\n AuthEngineError,\n AuthRequestSchema,\n AgentAuthRequestSchema,\n AgentContextSchema,\n MintTokenRequestSchema,\n DelegateScopeRequestSchema,\n} from \"./types.js\";\n\n// ─── Convenience factory ──────────────────────────────────────────────────────\n\nimport { LeluClient } from \"./client.js\";\nimport type { ClientConfig } from \"./types.js\";\n\n/**\n * Creates a LeluClient with the given configuration.\n * Equivalent to `new LeluClient(config)`.\n *\n * @example\n * ```ts\n * import { createClient } from \"@lelu-auth/lelu\";\n *\n * const lelu = createClient({ baseUrl: \"http://localhost:8080\" });\n * const { allowed } = await lelu.agentAuthorize({ ... });\n * ```\n */\nexport function createClient(config?: ClientConfig): LeluClient {\n return new LeluClient(config);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/vercel/index.ts","../src/types.ts","../src/client.ts","../src/index.ts"],"names":["z"],"mappings":";;;;;AAgGO,SAAS,WACd,IAAA,EAC+C;AAC/C,EAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,WAAU,GAAI,IAAA;AAE7C,EAAA,MAAM,OAAA,GAAyD;AAAA,IAC7D,UAAA,EAAY,KAAK,IAAA,CAAK,UAAA;AAAA,IAEtB,MAAM,OAAA,CACJ,IAAA,EACA,OAAA,EACqC;AAErC,MAAA,MAAM,UAAA,GACJ,OAAO,IAAA,CAAK,UAAA,KAAe,UAAA,GACvB,KAAK,UAAA,CAAW,IAAI,CAAA,GACnB,IAAA,CAAK,UAAA,IAAc,CAAA;AAE1B,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,MAAM,OAAO,cAAA,CAAe;AAAA,UACrC,KAAA;AAAA,UACA,MAAA;AAAA,UACA,OAAA,EAAS,EAAE,UAAA,EAAY,SAAA;AAAU,SAClC,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AAEZ,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,MAAA,EAAQ,CAAA,iCAAA,EAAoC,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,UACvD,mBAAA,EAAqB;AAAA,SACvB;AAAA,MACF;AAGA,MAAA,IAAI,SAAS,mBAAA,EAAqB;AAChC,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,MAAA,EACE,CAAA,QAAA,EAAW,MAAM,CAAA,aAAA,EAAgB,KAAK,CAAA,sCAAA,EAC3B,QAAA,CAAS,MAAM,CAAA,cAAA,EAAA,CAAkB,UAAA,GAAa,GAAA,EAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,EAAA,CAAA;AAAA,UAC1E,mBAAA,EAAqB;AAAA,SACvB;AAAA,MACF;AAGA,MAAA,IAAI,CAAC,SAAS,OAAA,EAAS;AACrB,QAAA,MAAM,MAAA,GAA2B;AAAA,UAC/B,OAAA,EAAS,KAAA;AAAA,UACT,QACE,CAAA,QAAA,EAAW,MAAM,2BAA2B,KAAK,CAAA,WAAA,EACtC,SAAS,MAAM,CAAA,CAAA,CAAA;AAAA,UAC5B,mBAAA,EAAqB;AAAA,SACvB;AACA,QAAA,IAAI,QAAA,CAAS,oBAAoB,MAAA,EAAW;AAC1C,UAAA,MAAA,CAAO,kBAAkB,QAAA,CAAS,eAAA;AAAA,QACpC;AACA,QAAA,OAAO;AAAA,UACL,GAAG;AAAA,SACL;AAAA,MACF;AAGA,MAAA,IAAI,CAAC,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS;AACtB,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,wCAAwC,MAAM,CAAA,0BAAA;AAAA,SAChD;AAAA,MACF;AACA,MAAA,OAAO,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA;AAAA,IACxC;AAAA,GACF;AAEA,EAAA,IAAI,IAAA,CAAK,IAAA,CAAK,WAAA,KAAgB,MAAA,EAAW;AACvC,IAAA,OAAA,CAAQ,WAAA,GAAc,KAAK,IAAA,CAAK,WAAA;AAAA,EAClC;AAEA,EAAA,OAAO,OAAA;AACT;ACzKO,IAAM,iBAAA,GAAoBA,MAAE,MAAA,CAAO;AAAA,EACxC,QAAQA,KAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,oBAAoB,CAAA;AAAA,EAC9C,QAAQA,KAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,oBAAoB,CAAA;AAAA,EAC9C,UAAUA,KAAA,CAAE,MAAA,CAAOA,MAAE,MAAA,EAAQ,EAAE,QAAA;AACjC,CAAC;AAEM,IAAM,kBAAA,GAAqBA,MAAE,MAAA,CAAO;AAAA;AAAA,EAEzC,UAAA,EAAYA,MAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEnC,SAAA,EAAWA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA,EAE/B,KAAA,EAAOA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACpB,CAAC;AAEM,IAAM,sBAAA,GAAyBA,MAAE,MAAA,CAAO;AAAA,EAC7C,OAAOA,KAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,mBAAmB,CAAA;AAAA,EAC5C,QAAQA,KAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,oBAAoB,CAAA;AAAA,EAC9C,UAAUA,KAAA,CAAE,MAAA,CAAOA,MAAE,MAAA,EAAQ,EAAE,QAAA,EAAS;AAAA,EACxC,OAAA,EAAS;AACX,CAAC;AAEM,IAAM,sBAAA,GAAyBA,MAAE,MAAA,CAAO;AAAA,EAC7C,KAAA,EAAOA,KAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACvB,SAAA,EAAWA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC/B,UAAA,EAAYA,MAAE,MAAA,EAAO,CAAE,KAAI,CAAE,QAAA,GAAW,QAAA;AAC1C,CAAC;AAEM,IAAM,0BAAA,GAA6BA,MAAE,MAAA,CAAO;AAAA,EACjD,WAAWA,KAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,uBAAuB,CAAA;AAAA,EACpD,WAAWA,KAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,uBAAuB,CAAA;AAAA,EACpD,QAAA,EAAUA,KAAA,CAAE,KAAA,CAAMA,KAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,CAAC,CAAA,CAAE,QAAA,EAAS;AAAA,EAC9C,UAAA,EAAYA,MAAE,MAAA,EAAO,CAAE,KAAI,CAAE,QAAA,GAAW,QAAA,EAAS;AAAA,EACjD,UAAA,EAAYA,KAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,QAAA,EAAS;AAAA,EAC9C,SAAA,EAAWA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC/B,QAAA,EAAUA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACvB,CAAC;AA2EM,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA,EACzC,WAAA,CACE,OAAA,EACgB,MAAA,EACA,OAAA,EAChB;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAHG,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;;;ACrFO,IAAM,aAAN,MAAiB;AAAA,EACL,OAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EAEjB,WAAA,CAAY,GAAA,GAAoB,EAAC,EAAG;AAClC,IAAA,MAAM,UAAA,GACJ,OAAO,OAAA,KAAY,WAAA,IAAe,QAAQ,GAAA,GACtC,OAAA,CAAQ,GAAA,CAAI,eAAe,CAAA,GAC3B,MAAA;AACN,IAAA,IAAA,CAAK,WAAW,GAAA,CAAI,OAAA,IAAW,cAAc,uBAAA,EAAyB,OAAA,CAAQ,OAAO,EAAE,CAAA;AACvF,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,SAAA,IAAa,GAAA;AAClC,IAAA,IAAA,CAAK,SAAS,GAAA,CAAI,MAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAU,GAAA,EAAyC;AACvD,IAAA,MAAM,SAAA,GAAY,iBAAA,CAAkB,KAAA,CAAM,GAAG,CAAA;AAC7C,IAAA,MAAM,IAAA,GAAO;AAAA,MACX,SAAS,SAAA,CAAU,MAAA;AAAA,MACnB,QAAQ,SAAA,CAAU,MAAA;AAAA,MAClB,UAAU,SAAA,CAAU;AAAA,KACtB;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAIrB,iBAAiB,IAAI,CAAA;AAExB,IAAA,OAAO;AAAA,MACL,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAe,GAAA,EAAmD;AACtE,IAAA,MAAM,SAAA,GAAY,sBAAA,CAAuB,KAAA,CAAM,GAAG,CAAA;AAClD,IAAA,MAAM,IAAA,GAAO;AAAA,MACX,OAAO,SAAA,CAAU,KAAA;AAAA,MACjB,QAAQ,SAAA,CAAU,MAAA;AAAA,MAClB,UAAU,SAAA,CAAU,QAAA;AAAA,MACpB,UAAA,EAAY,UAAU,OAAA,CAAQ,UAAA;AAAA,MAC9B,UAAA,EAAY,UAAU,OAAA,CAAQ,SAAA;AAAA,MAC9B,KAAA,EAAO,UAAU,OAAA,CAAQ;AAAA,KAC3B;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAOrB,uBAAuB,IAAI,CAAA;AAE9B,IAAA,OAAO;AAAA,MACL,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,QAAA;AAAA,MACd,iBAAiB,IAAA,CAAK,gBAAA;AAAA,MACtB,qBAAqB,IAAA,CAAK,qBAAA;AAAA,MAC1B,gBAAgB,IAAA,CAAK;AAAA,KACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAU,GAAA,EAAiD;AAC/D,IAAA,MAAM,SAAA,GAAY,sBAAA,CAAuB,KAAA,CAAM,GAAG,CAAA;AAClD,IAAA,MAAM,IAAA,GAAO;AAAA,MACX,OAAO,SAAA,CAAU,KAAA;AAAA,MACjB,YAAY,SAAA,CAAU,SAAA;AAAA,MACtB,WAAA,EAAa,UAAU,UAAA,IAAc;AAAA,KACvC;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAIrB,mBAAmB,IAAI,CAAA;AAE1B,IAAA,OAAO;AAAA,MACL,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,SAAS,IAAA,CAAK,QAAA;AAAA,MACd,SAAA,EAAW,IAAI,IAAA,CAAK,IAAA,CAAK,aAAa,GAAI;AAAA,KAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,YAAY,OAAA,EAA6C;AAC7D,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA;AAAA,MACtB,CAAA,WAAA,EAAc,kBAAA,CAAmB,OAAO,CAAC,CAAA;AAAA,KAC3C;AACA,IAAA,OAAO,EAAE,OAAA,EAAS,IAAA,CAAK,OAAA,EAAQ;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,cAAc,GAAA,EAAyD;AAC3E,IAAA,MAAM,SAAA,GAAY,0BAAA,CAA2B,KAAA,CAAM,GAAG,CAAA;AACtD,IAAA,MAAM,IAAA,GAAO;AAAA,MACX,WAAW,SAAA,CAAU,SAAA;AAAA,MACrB,WAAW,SAAA,CAAU,SAAA;AAAA,MACrB,SAAA,EAAW,SAAA,CAAU,QAAA,IAAY,EAAC;AAAA,MAClC,WAAA,EAAa,UAAU,UAAA,IAAc,EAAA;AAAA,MACrC,UAAA,EAAY,UAAU,UAAA,IAAc,CAAA;AAAA,MACpC,UAAA,EAAY,UAAU,SAAA,IAAa,EAAA;AAAA,MACnC,SAAA,EAAW,UAAU,QAAA,IAAY;AAAA,KACnC;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,CAQrB,sBAAsB,IAAI,CAAA;AAE7B,IAAA,OAAO;AAAA,MACL,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,SAAS,IAAA,CAAK,QAAA;AAAA,MACd,SAAA,EAAW,IAAI,IAAA,CAAK,IAAA,CAAK,aAAa,GAAI,CAAA;AAAA,MAC1C,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,eAAe,IAAA,CAAK,cAAA;AAAA,MACpB,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAAA,GAA8B;AAClC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,GAAA,CAAwB,UAAU,CAAA;AAC1D,MAAA,OAAO,KAAK,MAAA,KAAW,IAAA;AAAA,IACzB,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAIQ,OAAA,GAAkC;AACxC,IAAA,MAAM,CAAA,GAA4B,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AACvE,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,CAAA,CAAE,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,IAC5C;AACA,IAAA,OAAO,CAAA;AAAA,EACT;AAAA,EAEA,MAAc,IAAA,CAAQ,IAAA,EAAc,IAAA,EAA2B;AAC7D,IAAA,MAAM,IAAA,GAAO,IAAI,eAAA,EAAgB;AACjC,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,KAAK,KAAA,EAAM,EAAG,KAAK,SAAS,CAAA;AAC3D,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI;AAAA,QAChD,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,KAAK,OAAA,EAAQ;AAAA,QACtB,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAAA,QACzB,QAAQ,IAAA,CAAK;AAAA,OACd,CAAA;AACD,MAAA,OAAO,IAAA,CAAK,cAAiB,GAAG,CAAA;AAAA,IAClC,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAc,OAAU,IAAA,EAA0B;AAChD,IAAA,MAAM,IAAA,GAAO,IAAI,eAAA,EAAgB;AACjC,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,KAAK,KAAA,EAAM,EAAG,KAAK,SAAS,CAAA;AAC3D,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI;AAAA,QAChD,MAAA,EAAQ,QAAA;AAAA,QACR,OAAA,EAAS,KAAK,OAAA,EAAQ;AAAA,QACtB,QAAQ,IAAA,CAAK;AAAA,OACd,CAAA;AACD,MAAA,OAAO,IAAA,CAAK,cAAiB,GAAG,CAAA;AAAA,IAClC,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAc,IAAO,IAAA,EAA0B;AAC7C,IAAA,MAAM,IAAA,GAAO,IAAI,eAAA,EAAgB;AACjC,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,KAAK,KAAA,EAAM,EAAG,KAAK,SAAS,CAAA;AAC3D,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI;AAAA,QAChD,MAAA,EAAQ,KAAA;AAAA,QACR,OAAA,EAAS,KAAK,OAAA,EAAQ;AAAA,QACtB,QAAQ,IAAA,CAAK;AAAA,OACd,CAAA;AACD,MAAA,OAAO,IAAA,CAAK,cAAiB,GAAG,CAAA;AAAA,IAClC,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAc,cAAiB,GAAA,EAA2B;AACxD,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAI,eAAA;AAAA,QACP,IAAA,CAAK,OAAO,CAAA,IAAgB,cAAA;AAAA,QAC7B,GAAA,CAAI,MAAA;AAAA,QACJ;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;ACjOO,SAAS,aAAa,MAAA,EAAmC;AAC9D,EAAA,OAAO,IAAI,WAAW,MAAM,CAAA;AAC9B","file":"index.js","sourcesContent":["/**\r\n * Vercel AI SDK integration for Lelu — Confidence-Aware Auth.\r\n *\r\n * Wraps a Vercel AI SDK `tool()` definition with a Lelu authorization\r\n * gate. The wrapped tool runs the original `execute` function only when\r\n * Lelu allows it; otherwise it returns a structured refusal object that\r\n * the model can inspect and self-correct on.\r\n *\r\n * @example\r\n * ```ts\r\n * import { tool } from 'ai';\r\n * import { z } from 'zod';\r\n * import { LeluClient } from '@lelu-auth/lelu';\r\n * import { secureTool } from 'lelu/vercel';\r\n *\r\n * const lelu = new LeluClient({ baseUrl: 'http://localhost:8082' });\r\n *\r\n * const refundTool = secureTool({\r\n * client: lelu,\r\n * actor: 'invoice_bot',\r\n * action: 'invoice:refund',\r\n * confidence: 0.92,\r\n * tool: tool({\r\n * description: 'Process a customer refund',\r\n * parameters: z.object({ invoiceId: z.string() }),\r\n * execute: async ({ invoiceId }) => ({ refunded: invoiceId }),\r\n * }),\r\n * });\r\n *\r\n * // Use in streamText / generateText:\r\n * const result = await streamText({\r\n * model: openai('gpt-4o'),\r\n * tools: { refundTool },\r\n * });\r\n * ```\r\n */\r\n\r\nimport { LeluClient } from \"../client.js\";\r\n\r\n// ─── Minimal Vercel AI SDK tool type ──────────────────────────────────────────\r\n\r\n/**\r\n * The minimal shape of a Vercel AI SDK `tool()` return value.\r\n * We keep this local to avoid a hard dependency on `ai`.\r\n */\r\nexport interface VercelTool<TArgs = unknown, TResult = unknown> {\r\n description?: string;\r\n parameters: unknown;\r\n execute?: (args: TArgs, options?: unknown) => Promise<TResult>;\r\n}\r\n\r\n// ─── Denied / Review result shape ─────────────────────────────────────────────\r\n\r\nexport interface LeluDeniedResult {\r\n /** Always `false` when the tool was blocked. */\r\n allowed: false;\r\n /** Human/LLM-readable denial reason. */\r\n reason: string;\r\n /** Whether the action is queued for human review. */\r\n requiresHumanReview: boolean;\r\n /** The downgraded scope when confidence caused a downgrade. */\r\n downgradedScope?: string;\r\n}\r\n\r\n// ─── Options ──────────────────────────────────────────────────────────────────\r\n\r\nexport interface SecureToolOptions<TArgs = unknown, TResult = unknown> {\r\n /** Configured Lelu client. */\r\n client: LeluClient;\r\n /** The agent actor / scope registered in Lelu policy. */\r\n actor: string;\r\n /** The permission string being checked. */\r\n action: string;\r\n /**\r\n * LLM confidence score (0.0–1.0). Can be a static number or a function\r\n * receiving the parsed tool arguments, allowing dynamic confidence based\r\n * on the actual call. Defaults to `1.0`.\r\n */\r\n confidence?: number | ((args: TArgs) => number);\r\n /** Optional user ID the agent is acting on behalf of. */\r\n actingFor?: string;\r\n /** The original Vercel AI SDK tool to wrap. */\r\n tool: VercelTool<TArgs, TResult>;\r\n}\r\n\r\n// ─── secureTool ───────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Wraps a Vercel AI SDK `tool()` with Lelu Confidence-Aware Auth.\r\n *\r\n * Returns a new tool object with the same `description` and `parameters`\r\n * but with an `execute` function that gates through Lelu first.\r\n *\r\n * On denial the tool returns a `LeluDeniedResult` object (not a throw) so\r\n * the model sees a structured response it can reason about.\r\n */\r\nexport function secureTool<TArgs = unknown, TResult = unknown>(\r\n opts: SecureToolOptions<TArgs, TResult>\r\n): VercelTool<TArgs, TResult | LeluDeniedResult> {\r\n const { client, actor, action, actingFor } = opts;\r\n\r\n const wrapped: VercelTool<TArgs, TResult | LeluDeniedResult> = {\r\n parameters: opts.tool.parameters,\r\n\r\n async execute(\r\n args: TArgs,\r\n options?: unknown\r\n ): Promise<TResult | LeluDeniedResult> {\r\n // Resolve confidence — static number or dynamic function.\r\n const confidence =\r\n typeof opts.confidence === \"function\"\r\n ? opts.confidence(args)\r\n : (opts.confidence ?? 1.0);\r\n\r\n let decision;\r\n try {\r\n decision = await client.agentAuthorize({\r\n actor,\r\n action,\r\n context: { confidence, actingFor },\r\n });\r\n } catch (err) {\r\n // Fail open with a structured denial so the model can handle it.\r\n return {\r\n allowed: false,\r\n reason: `Lelu authorization check failed: ${String(err)}`,\r\n requiresHumanReview: false,\r\n };\r\n }\r\n\r\n // ── Human review required ──────────────────────────────────────────\r\n if (decision.requiresHumanReview) {\r\n return {\r\n allowed: false,\r\n reason:\r\n `Action '${action}' for agent '${actor}' is queued for human review. ` +\r\n `Reason: ${decision.reason}. Confidence: ${(confidence * 100).toFixed(0)}%.`,\r\n requiresHumanReview: true,\r\n };\r\n }\r\n\r\n // ── Hard deny ─────────────────────────────────────────────────────\r\n if (!decision.allowed) {\r\n const denied: LeluDeniedResult = {\r\n allowed: false,\r\n reason:\r\n `Action '${action}' was denied for agent '${actor}'. ` +\r\n `Reason: ${decision.reason}.`,\r\n requiresHumanReview: false,\r\n };\r\n if (decision.downgradedScope !== undefined) {\r\n denied.downgradedScope = decision.downgradedScope;\r\n }\r\n return {\r\n ...denied,\r\n };\r\n }\r\n\r\n // ── Authorized — run original execute ─────────────────────────────\r\n if (!opts.tool.execute) {\r\n throw new Error(\r\n `[Lelu] secureTool: the wrapped tool '${action}' has no execute function.`\r\n );\r\n }\r\n return opts.tool.execute(args, options);\r\n },\r\n };\r\n\r\n if (opts.tool.description !== undefined) {\r\n wrapped.description = opts.tool.description;\r\n }\r\n\r\n return wrapped;\r\n}\r\n","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","// Auth Permission Engine — TypeScript SDK\r\n// Public API surface\r\n\r\n// ─── Vercel AI SDK integration ────────────────────────────────────────────────\r\n// Import via: import { secureTool } from 'lelu/vercel'\r\n// (tree-shakeable — does not add weight to non-Vercel users)\r\nexport { secureTool } from \"./vercel/index.js\";\r\nexport type { SecureToolOptions, LeluDeniedResult, VercelTool } from \"./vercel/index.js\";\r\n\r\nexport { LeluClient } from \"./client.js\";\r\n\r\nexport type {\r\n AuthRequest,\r\n AgentAuthRequest,\r\n AgentContext,\r\n MintTokenRequest,\r\n DelegateScopeRequest,\r\n AuthDecision,\r\n AgentAuthDecision,\r\n MintTokenResult,\r\n DelegateScopeResult,\r\n RevokeTokenResult,\r\n ClientConfig,\r\n} from \"./types.js\";\r\n\r\nexport {\r\n AuthEngineError,\r\n AuthRequestSchema,\r\n AgentAuthRequestSchema,\r\n AgentContextSchema,\r\n MintTokenRequestSchema,\r\n DelegateScopeRequestSchema,\r\n} from \"./types.js\";\r\n\r\n// ─── Convenience factory ──────────────────────────────────────────────────────\r\n\r\nimport { LeluClient } from \"./client.js\";\r\nimport type { ClientConfig } from \"./types.js\";\r\n\r\n/**\r\n * Creates a LeluClient with the given configuration.\r\n * Equivalent to `new LeluClient(config)`.\r\n *\r\n * @example\r\n * ```ts\r\n * import { createClient } from \"@lelu-auth/lelu\";\r\n *\r\n * const lelu = createClient({ baseUrl: \"http://localhost:8080\" });\r\n * const { allowed } = await lelu.agentAuthorize({ ... });\r\n * ```\r\n */\r\nexport function createClient(config?: ClientConfig): LeluClient {\r\n return new LeluClient(config);\r\n}\r\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -102,7 +102,8 @@ var LeluClient = class {
|
|
|
102
102
|
timeoutMs;
|
|
103
103
|
apiKey;
|
|
104
104
|
constructor(cfg = {}) {
|
|
105
|
-
|
|
105
|
+
const envBaseUrl = typeof process !== "undefined" && process.env ? process.env["LELU_BASE_URL"] : void 0;
|
|
106
|
+
this.baseUrl = (cfg.baseUrl ?? envBaseUrl ?? "http://localhost:8080").replace(/\/$/, "");
|
|
106
107
|
this.timeoutMs = cfg.timeoutMs ?? 5e3;
|
|
107
108
|
this.apiKey = cfg.apiKey;
|
|
108
109
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vercel/index.ts","../src/types.ts","../src/client.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Vercel AI SDK integration for Lelu — Confidence-Aware Auth.\n *\n * Wraps a Vercel AI SDK `tool()` definition with a Lelu authorization\n * gate. The wrapped tool runs the original `execute` function only when\n * Lelu allows it; otherwise it returns a structured refusal object that\n * the model can inspect and self-correct on.\n *\n * @example\n * ```ts\n * import { tool } from 'ai';\n * import { z } from 'zod';\n * import { LeluClient } from '@lelu-auth/lelu';\n * import { secureTool } from 'lelu/vercel';\n *\n * const lelu = new LeluClient({ baseUrl: 'http://localhost:8082' });\n *\n * const refundTool = secureTool({\n * client: lelu,\n * actor: 'invoice_bot',\n * action: 'invoice:refund',\n * confidence: 0.92,\n * tool: tool({\n * description: 'Process a customer refund',\n * parameters: z.object({ invoiceId: z.string() }),\n * execute: async ({ invoiceId }) => ({ refunded: invoiceId }),\n * }),\n * });\n *\n * // Use in streamText / generateText:\n * const result = await streamText({\n * model: openai('gpt-4o'),\n * tools: { refundTool },\n * });\n * ```\n */\n\nimport { LeluClient } from \"../client.js\";\n\n// ─── Minimal Vercel AI SDK tool type ──────────────────────────────────────────\n\n/**\n * The minimal shape of a Vercel AI SDK `tool()` return value.\n * We keep this local to avoid a hard dependency on `ai`.\n */\nexport interface VercelTool<TArgs = unknown, TResult = unknown> {\n description?: string;\n parameters: unknown;\n execute?: (args: TArgs, options?: unknown) => Promise<TResult>;\n}\n\n// ─── Denied / Review result shape ─────────────────────────────────────────────\n\nexport interface LeluDeniedResult {\n /** Always `false` when the tool was blocked. */\n allowed: false;\n /** Human/LLM-readable denial reason. */\n reason: string;\n /** Whether the action is queued for human review. */\n requiresHumanReview: boolean;\n /** The downgraded scope when confidence caused a downgrade. */\n downgradedScope?: string;\n}\n\n// ─── Options ──────────────────────────────────────────────────────────────────\n\nexport interface SecureToolOptions<TArgs = unknown, TResult = unknown> {\n /** Configured Lelu client. */\n client: LeluClient;\n /** The agent actor / scope registered in Lelu policy. */\n actor: string;\n /** The permission string being checked. */\n action: string;\n /**\n * LLM confidence score (0.0–1.0). Can be a static number or a function\n * receiving the parsed tool arguments, allowing dynamic confidence based\n * on the actual call. Defaults to `1.0`.\n */\n confidence?: number | ((args: TArgs) => number);\n /** Optional user ID the agent is acting on behalf of. */\n actingFor?: string;\n /** The original Vercel AI SDK tool to wrap. */\n tool: VercelTool<TArgs, TResult>;\n}\n\n// ─── secureTool ───────────────────────────────────────────────────────────────\n\n/**\n * Wraps a Vercel AI SDK `tool()` with Lelu Confidence-Aware Auth.\n *\n * Returns a new tool object with the same `description` and `parameters`\n * but with an `execute` function that gates through Lelu first.\n *\n * On denial the tool returns a `LeluDeniedResult` object (not a throw) so\n * the model sees a structured response it can reason about.\n */\nexport function secureTool<TArgs = unknown, TResult = unknown>(\n opts: SecureToolOptions<TArgs, TResult>\n): VercelTool<TArgs, TResult | LeluDeniedResult> {\n const { client, actor, action, actingFor } = opts;\n\n const wrapped: VercelTool<TArgs, TResult | LeluDeniedResult> = {\n parameters: opts.tool.parameters,\n\n async execute(\n args: TArgs,\n options?: unknown\n ): Promise<TResult | LeluDeniedResult> {\n // Resolve confidence — static number or dynamic function.\n const confidence =\n typeof opts.confidence === \"function\"\n ? opts.confidence(args)\n : (opts.confidence ?? 1.0);\n\n let decision;\n try {\n decision = await client.agentAuthorize({\n actor,\n action,\n context: { confidence, actingFor },\n });\n } catch (err) {\n // Fail open with a structured denial so the model can handle it.\n return {\n allowed: false,\n reason: `Lelu authorization check failed: ${String(err)}`,\n requiresHumanReview: false,\n };\n }\n\n // ── Human review required ──────────────────────────────────────────\n if (decision.requiresHumanReview) {\n return {\n allowed: false,\n reason:\n `Action '${action}' for agent '${actor}' is queued for human review. ` +\n `Reason: ${decision.reason}. Confidence: ${(confidence * 100).toFixed(0)}%.`,\n requiresHumanReview: true,\n };\n }\n\n // ── Hard deny ─────────────────────────────────────────────────────\n if (!decision.allowed) {\n const denied: LeluDeniedResult = {\n allowed: false,\n reason:\n `Action '${action}' was denied for agent '${actor}'. ` +\n `Reason: ${decision.reason}.`,\n requiresHumanReview: false,\n };\n if (decision.downgradedScope !== undefined) {\n denied.downgradedScope = decision.downgradedScope;\n }\n return {\n ...denied,\n };\n }\n\n // ── Authorized — run original execute ─────────────────────────────\n if (!opts.tool.execute) {\n throw new Error(\n `[Lelu] secureTool: the wrapped tool '${action}' has no execute function.`\n );\n }\n return opts.tool.execute(args, options);\n },\n };\n\n if (opts.tool.description !== undefined) {\n wrapped.description = opts.tool.description;\n }\n\n return wrapped;\n}\n","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","// Auth Permission Engine — TypeScript SDK\n// Public API surface\n\n// ─── Vercel AI SDK integration ────────────────────────────────────────────────\n// Import via: import { secureTool } from 'lelu/vercel'\n// (tree-shakeable — does not add weight to non-Vercel users)\nexport { secureTool } from \"./vercel/index.js\";\nexport type { SecureToolOptions, LeluDeniedResult, VercelTool } from \"./vercel/index.js\";\n\nexport { LeluClient } from \"./client.js\";\n\nexport type {\n AuthRequest,\n AgentAuthRequest,\n AgentContext,\n MintTokenRequest,\n DelegateScopeRequest,\n AuthDecision,\n AgentAuthDecision,\n MintTokenResult,\n DelegateScopeResult,\n RevokeTokenResult,\n ClientConfig,\n} from \"./types.js\";\n\nexport {\n AuthEngineError,\n AuthRequestSchema,\n AgentAuthRequestSchema,\n AgentContextSchema,\n MintTokenRequestSchema,\n DelegateScopeRequestSchema,\n} from \"./types.js\";\n\n// ─── Convenience factory ──────────────────────────────────────────────────────\n\nimport { LeluClient } from \"./client.js\";\nimport type { ClientConfig } from \"./types.js\";\n\n/**\n * Creates a LeluClient with the given configuration.\n * Equivalent to `new LeluClient(config)`.\n *\n * @example\n * ```ts\n * import { createClient } from \"@lelu-auth/lelu\";\n *\n * const lelu = createClient({ baseUrl: \"http://localhost:8080\" });\n * const { allowed } = await lelu.agentAuthorize({ ... });\n * ```\n */\nexport function createClient(config?: ClientConfig): LeluClient {\n return new LeluClient(config);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/vercel/index.ts","../src/types.ts","../src/client.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * Vercel AI SDK integration for Lelu — Confidence-Aware Auth.\r\n *\r\n * Wraps a Vercel AI SDK `tool()` definition with a Lelu authorization\r\n * gate. The wrapped tool runs the original `execute` function only when\r\n * Lelu allows it; otherwise it returns a structured refusal object that\r\n * the model can inspect and self-correct on.\r\n *\r\n * @example\r\n * ```ts\r\n * import { tool } from 'ai';\r\n * import { z } from 'zod';\r\n * import { LeluClient } from '@lelu-auth/lelu';\r\n * import { secureTool } from 'lelu/vercel';\r\n *\r\n * const lelu = new LeluClient({ baseUrl: 'http://localhost:8082' });\r\n *\r\n * const refundTool = secureTool({\r\n * client: lelu,\r\n * actor: 'invoice_bot',\r\n * action: 'invoice:refund',\r\n * confidence: 0.92,\r\n * tool: tool({\r\n * description: 'Process a customer refund',\r\n * parameters: z.object({ invoiceId: z.string() }),\r\n * execute: async ({ invoiceId }) => ({ refunded: invoiceId }),\r\n * }),\r\n * });\r\n *\r\n * // Use in streamText / generateText:\r\n * const result = await streamText({\r\n * model: openai('gpt-4o'),\r\n * tools: { refundTool },\r\n * });\r\n * ```\r\n */\r\n\r\nimport { LeluClient } from \"../client.js\";\r\n\r\n// ─── Minimal Vercel AI SDK tool type ──────────────────────────────────────────\r\n\r\n/**\r\n * The minimal shape of a Vercel AI SDK `tool()` return value.\r\n * We keep this local to avoid a hard dependency on `ai`.\r\n */\r\nexport interface VercelTool<TArgs = unknown, TResult = unknown> {\r\n description?: string;\r\n parameters: unknown;\r\n execute?: (args: TArgs, options?: unknown) => Promise<TResult>;\r\n}\r\n\r\n// ─── Denied / Review result shape ─────────────────────────────────────────────\r\n\r\nexport interface LeluDeniedResult {\r\n /** Always `false` when the tool was blocked. */\r\n allowed: false;\r\n /** Human/LLM-readable denial reason. */\r\n reason: string;\r\n /** Whether the action is queued for human review. */\r\n requiresHumanReview: boolean;\r\n /** The downgraded scope when confidence caused a downgrade. */\r\n downgradedScope?: string;\r\n}\r\n\r\n// ─── Options ──────────────────────────────────────────────────────────────────\r\n\r\nexport interface SecureToolOptions<TArgs = unknown, TResult = unknown> {\r\n /** Configured Lelu client. */\r\n client: LeluClient;\r\n /** The agent actor / scope registered in Lelu policy. */\r\n actor: string;\r\n /** The permission string being checked. */\r\n action: string;\r\n /**\r\n * LLM confidence score (0.0–1.0). Can be a static number or a function\r\n * receiving the parsed tool arguments, allowing dynamic confidence based\r\n * on the actual call. Defaults to `1.0`.\r\n */\r\n confidence?: number | ((args: TArgs) => number);\r\n /** Optional user ID the agent is acting on behalf of. */\r\n actingFor?: string;\r\n /** The original Vercel AI SDK tool to wrap. */\r\n tool: VercelTool<TArgs, TResult>;\r\n}\r\n\r\n// ─── secureTool ───────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Wraps a Vercel AI SDK `tool()` with Lelu Confidence-Aware Auth.\r\n *\r\n * Returns a new tool object with the same `description` and `parameters`\r\n * but with an `execute` function that gates through Lelu first.\r\n *\r\n * On denial the tool returns a `LeluDeniedResult` object (not a throw) so\r\n * the model sees a structured response it can reason about.\r\n */\r\nexport function secureTool<TArgs = unknown, TResult = unknown>(\r\n opts: SecureToolOptions<TArgs, TResult>\r\n): VercelTool<TArgs, TResult | LeluDeniedResult> {\r\n const { client, actor, action, actingFor } = opts;\r\n\r\n const wrapped: VercelTool<TArgs, TResult | LeluDeniedResult> = {\r\n parameters: opts.tool.parameters,\r\n\r\n async execute(\r\n args: TArgs,\r\n options?: unknown\r\n ): Promise<TResult | LeluDeniedResult> {\r\n // Resolve confidence — static number or dynamic function.\r\n const confidence =\r\n typeof opts.confidence === \"function\"\r\n ? opts.confidence(args)\r\n : (opts.confidence ?? 1.0);\r\n\r\n let decision;\r\n try {\r\n decision = await client.agentAuthorize({\r\n actor,\r\n action,\r\n context: { confidence, actingFor },\r\n });\r\n } catch (err) {\r\n // Fail open with a structured denial so the model can handle it.\r\n return {\r\n allowed: false,\r\n reason: `Lelu authorization check failed: ${String(err)}`,\r\n requiresHumanReview: false,\r\n };\r\n }\r\n\r\n // ── Human review required ──────────────────────────────────────────\r\n if (decision.requiresHumanReview) {\r\n return {\r\n allowed: false,\r\n reason:\r\n `Action '${action}' for agent '${actor}' is queued for human review. ` +\r\n `Reason: ${decision.reason}. Confidence: ${(confidence * 100).toFixed(0)}%.`,\r\n requiresHumanReview: true,\r\n };\r\n }\r\n\r\n // ── Hard deny ─────────────────────────────────────────────────────\r\n if (!decision.allowed) {\r\n const denied: LeluDeniedResult = {\r\n allowed: false,\r\n reason:\r\n `Action '${action}' was denied for agent '${actor}'. ` +\r\n `Reason: ${decision.reason}.`,\r\n requiresHumanReview: false,\r\n };\r\n if (decision.downgradedScope !== undefined) {\r\n denied.downgradedScope = decision.downgradedScope;\r\n }\r\n return {\r\n ...denied,\r\n };\r\n }\r\n\r\n // ── Authorized — run original execute ─────────────────────────────\r\n if (!opts.tool.execute) {\r\n throw new Error(\r\n `[Lelu] secureTool: the wrapped tool '${action}' has no execute function.`\r\n );\r\n }\r\n return opts.tool.execute(args, options);\r\n },\r\n };\r\n\r\n if (opts.tool.description !== undefined) {\r\n wrapped.description = opts.tool.description;\r\n }\r\n\r\n return wrapped;\r\n}\r\n","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","// Auth Permission Engine — TypeScript SDK\r\n// Public API surface\r\n\r\n// ─── Vercel AI SDK integration ────────────────────────────────────────────────\r\n// Import via: import { secureTool } from 'lelu/vercel'\r\n// (tree-shakeable — does not add weight to non-Vercel users)\r\nexport { secureTool } from \"./vercel/index.js\";\r\nexport type { SecureToolOptions, LeluDeniedResult, VercelTool } from \"./vercel/index.js\";\r\n\r\nexport { LeluClient } from \"./client.js\";\r\n\r\nexport type {\r\n AuthRequest,\r\n AgentAuthRequest,\r\n AgentContext,\r\n MintTokenRequest,\r\n DelegateScopeRequest,\r\n AuthDecision,\r\n AgentAuthDecision,\r\n MintTokenResult,\r\n DelegateScopeResult,\r\n RevokeTokenResult,\r\n ClientConfig,\r\n} from \"./types.js\";\r\n\r\nexport {\r\n AuthEngineError,\r\n AuthRequestSchema,\r\n AgentAuthRequestSchema,\r\n AgentContextSchema,\r\n MintTokenRequestSchema,\r\n DelegateScopeRequestSchema,\r\n} from \"./types.js\";\r\n\r\n// ─── Convenience factory ──────────────────────────────────────────────────────\r\n\r\nimport { LeluClient } from \"./client.js\";\r\nimport type { ClientConfig } from \"./types.js\";\r\n\r\n/**\r\n * Creates a LeluClient with the given configuration.\r\n * Equivalent to `new LeluClient(config)`.\r\n *\r\n * @example\r\n * ```ts\r\n * import { createClient } from \"@lelu-auth/lelu\";\r\n *\r\n * const lelu = createClient({ baseUrl: \"http://localhost:8080\" });\r\n * const { allowed } = await lelu.agentAuthorize({ ... });\r\n * ```\r\n */\r\nexport function createClient(config?: ClientConfig): LeluClient {\r\n return new LeluClient(config);\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/langchain/secure-tool.ts","../../src/langchain/SemanticPolicyGenerator.ts"],"names":["OpenAI"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * SecureTool — LangChain tool wrapper with Confidence-Aware Auth\n *\n * Intercepts every tool call and gates it through the Lelu engine before\n * execution. Returns a structured refusal string when denied so the LLM can\n * self-correct, queue for human review, or escalate.\n *\n * Usage:\n * ```typescript\n * import { SecureTool } from 'lelu/langchain';\n *\n * const refundTool = new SecureTool({\n * name: 'process_refund',\n * description: 'Processes a customer refund',\n * actor: 'invoice_bot',\n * requiredPermission: 'invoice:refund',\n * client: leluClient,\n * func: async (input) => {\n * // your tool implementation\n * return `Refund processed for ${input}`;\n * },\n * });\n * ```\n */\n\nimport { LeluClient } from \"../client.js\";\n\n// ─── Minimal LangChain-compatible interface ───────────────────────────────────\n\n/** Minimal interface a wrapped tool must expose. */\nexport interface ToolLike {\n name: string;\n description: string;\n /** LangChain StructuredTool / DynamicTool use `invoke`. */\n invoke?: (input: string, ...args: unknown[]) => Promise<string>;\n /** Older LangChain versions use `call`. */\n call?: (input: string, ...args: unknown[]) => Promise<string>;\n}\n\n// ─── Options ──────────────────────────────────────────────────────────────────\n\nexport interface SecureToolOptions {\n /** Unique tool name (used as the action in authz request). */\n name: string;\n /** Human-readable description forwarded to the LLM. */\n description: string;\n /** The Lelu agent scope / actor name. */\n actor: string;\n /** The permission string being checked (e.g. \"invoice:refund\"). */\n requiredPermission: string;\n /** Configured LeluClient. */\n client: LeluClient;\n /** The actual tool function to execute when authorized. */\n func: (input: string) => Promise<string>;\n /**\n * Optional: LLM confidence score for this invocation (0.0–1.0).\n * If omitted, defaults to 1.0 (full confidence assumed).\n */\n confidence?: number;\n /**\n * Optional: the human user the agent is acting on behalf of.\n */\n actingFor?: string;\n /**\n * Optional: if true, throw an error when denied instead of returning\n * a structured refusal string. Default: false (silent fail, structured msg).\n */\n throwOnDeny?: boolean;\n}\n\n// ─── Result ───────────────────────────────────────────────────────────────────\n\nexport interface ToolCallResult {\n allowed: boolean;\n output: string;\n requiresHumanReview: boolean;\n reviewId?: string;\n reason: string;\n}\n\n// ─── SecureTool ───────────────────────────────────────────────────────────────\n\n/**\n * SecureTool wraps a tool function with Lelu's Confidence-Aware Auth gate.\n *\n * Implements the LangChain Tool interface (name + description + invoke)\n * so it can be dropped into any LangChain agent tool array:\n * ```typescript\n * const agent = await createOpenAIFunctionsAgent({ tools: [refundTool] });\n * ```\n */\nexport class SecureTool {\n readonly name: string;\n readonly description: string;\n\n private readonly opts: SecureToolOptions;\n\n constructor(opts: SecureToolOptions) {\n this.opts = opts;\n this.name = opts.name;\n this.description = opts.description;\n }\n\n /**\n * invoke — LangChain StructuredTool / DynamicTool compatible entry point.\n *\n * 1. Calls Lelu `agentAuthorize` with the confidence score\n * 2a. Allowed → runs the wrapped tool function\n * 2b. Requires human review → returns structured \"pending\" message\n * 2c. Denied → returns structured refusal string (LLM can self-correct)\n */\n async invoke(input: string): Promise<string> {\n const result = await this._check(input);\n if (result.allowed) {\n return result.output;\n }\n if (this.opts.throwOnDeny) {\n throw new Error(`[Lelu] Tool \"${this.name}\" denied: ${result.reason}`);\n }\n return result.output; // structured refusal or pending message\n }\n\n /** call — alias for older LangChain versions. */\n async call(input: string): Promise<string> {\n return this.invoke(input);\n }\n\n /**\n * Check authorization and run the tool if permitted.\n * Returns a full ToolCallResult for programmatic consumers.\n */\n async checkAndCall(input: string): Promise<ToolCallResult> {\n return this._check(input);\n }\n\n private async _check(input: string): Promise<ToolCallResult> {\n const { actor, requiredPermission, client, func, throwOnDeny } = this.opts;\n const confidence = this.opts.confidence ?? 1.0;\n const actingFor = this.opts.actingFor ?? \"\";\n\n let decision;\n try {\n decision = await client.agentAuthorize({\n actor,\n action: requiredPermission,\n context: {\n confidence,\n actingFor,\n },\n });\n } catch (err) {\n const msg = `[Lelu] Authorization check failed for \"${this.name}\": ${String(err)}`;\n if (throwOnDeny) throw new Error(msg);\n return {\n allowed: false,\n output: msg,\n requiresHumanReview: false,\n reason: String(err),\n };\n }\n\n // Human review required — queue and return pending message.\n if (decision.requiresHumanReview) {\n const msg =\n `[Lelu] Action \"${this.name}\" is queued for human review. ` +\n `Reason: ${decision.reason}. Please wait for approval before proceeding.`;\n return {\n allowed: false,\n output: msg,\n requiresHumanReview: true,\n reason: decision.reason,\n };\n }\n\n // Hard deny — return structured refusal.\n if (!decision.allowed) {\n const msg =\n `[Lelu] Action \"${this.name}\" was denied. ` +\n `Reason: ${decision.reason}. ` +\n `Downgraded scope: ${decision.downgradedScope ?? \"none\"}.`;\n return {\n allowed: false,\n output: msg,\n requiresHumanReview: false,\n reason: decision.reason,\n };\n }\n\n // Authorized — run the tool.\n const output = await func(input);\n return {\n allowed: true,\n output,\n requiresHumanReview: false,\n reason: decision.reason,\n };\n }\n}\n","import { OpenAI } from 'openai';\n\nexport class SemanticPolicyGenerator {\n private openai: OpenAI;\n\n constructor(apiKey: string) {\n this.openai = new OpenAI({ apiKey });\n }\n\n /**\n * Converts a natural language description into a deterministic Rego policy.\n * \n * @param description Natural language description of the policy (e.g., \"Don't let the bot refund more than $50 unless approved by a finance manager.\")\n * @param packageName The Rego package name (default: \"lelu.authz\")\n * @returns The generated Rego policy string\n */\n async generateRegoPolicy(description: string, packageName: string = \"lelu.authz\"): Promise<string> {\n const prompt = `\nYou are an expert in Open Policy Agent (OPA) Rego policies.\nYour task is to convert the following natural language description into a valid, deterministic Rego policy for the Lelu Auth Permission Engine.\n\nThe policy must output an object with the following structure:\n{\n \"allowed\": bool,\n \"reason\": string,\n \"downgraded_scope\": string (optional),\n \"requires_human_review\": bool (optional)\n}\n\nThe input to the policy will be an object with the following structure:\n{\n \"kind\": \"agent\" | \"human\",\n \"actor\": string,\n \"action\": string,\n \"resource\": map[string]any,\n \"confidence\": number (0.0 to 1.0),\n \"acting_for\": string,\n \"scope\": string\n}\n\nNatural Language Description:\n\"${description}\"\n\nPackage Name:\npackage ${packageName}\n\nRequirements:\n1. Output ONLY valid Rego code.\n2. Do not include markdown formatting (like \\`\\`\\`rego).\n3. Ensure the default state is deny (default allowed = false).\n4. Include comments explaining the logic.\n`;\n\n const response = await this.openai.chat.completions.create({\n model: \"gpt-4-turbo-preview\",\n messages: [\n { role: \"system\", content: \"You are a Rego policy generation assistant. Output only raw Rego code.\" },\n { role: \"user\", content: prompt }\n ],\n temperature: 0.1,\n });\n\n const regoCode = response.choices[0]?.message.content?.trim() || \"\";\n \n // Strip markdown code blocks if the LLM accidentally included them\n return regoCode.replace(/^```rego\\n/, '').replace(/\\n```$/, '');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/langchain/secure-tool.ts","../../src/langchain/SemanticPolicyGenerator.ts"],"names":["OpenAI"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * SecureTool — LangChain tool wrapper with Confidence-Aware Auth\r\n *\r\n * Intercepts every tool call and gates it through the Lelu engine before\r\n * execution. Returns a structured refusal string when denied so the LLM can\r\n * self-correct, queue for human review, or escalate.\r\n *\r\n * Usage:\r\n * ```typescript\r\n * import { SecureTool } from 'lelu/langchain';\r\n *\r\n * const refundTool = new SecureTool({\r\n * name: 'process_refund',\r\n * description: 'Processes a customer refund',\r\n * actor: 'invoice_bot',\r\n * requiredPermission: 'invoice:refund',\r\n * client: leluClient,\r\n * func: async (input) => {\r\n * // your tool implementation\r\n * return `Refund processed for ${input}`;\r\n * },\r\n * });\r\n * ```\r\n */\r\n\r\nimport { LeluClient } from \"../client.js\";\r\n\r\n// ─── Minimal LangChain-compatible interface ───────────────────────────────────\r\n\r\n/** Minimal interface a wrapped tool must expose. */\r\nexport interface ToolLike {\r\n name: string;\r\n description: string;\r\n /** LangChain StructuredTool / DynamicTool use `invoke`. */\r\n invoke?: (input: string, ...args: unknown[]) => Promise<string>;\r\n /** Older LangChain versions use `call`. */\r\n call?: (input: string, ...args: unknown[]) => Promise<string>;\r\n}\r\n\r\n// ─── Options ──────────────────────────────────────────────────────────────────\r\n\r\nexport interface SecureToolOptions {\r\n /** Unique tool name (used as the action in authz request). */\r\n name: string;\r\n /** Human-readable description forwarded to the LLM. */\r\n description: string;\r\n /** The Lelu agent scope / actor name. */\r\n actor: string;\r\n /** The permission string being checked (e.g. \"invoice:refund\"). */\r\n requiredPermission: string;\r\n /** Configured LeluClient. */\r\n client: LeluClient;\r\n /** The actual tool function to execute when authorized. */\r\n func: (input: string) => Promise<string>;\r\n /**\r\n * Optional: LLM confidence score for this invocation (0.0–1.0).\r\n * If omitted, defaults to 1.0 (full confidence assumed).\r\n */\r\n confidence?: number;\r\n /**\r\n * Optional: the human user the agent is acting on behalf of.\r\n */\r\n actingFor?: string;\r\n /**\r\n * Optional: if true, throw an error when denied instead of returning\r\n * a structured refusal string. Default: false (silent fail, structured msg).\r\n */\r\n throwOnDeny?: boolean;\r\n}\r\n\r\n// ─── Result ───────────────────────────────────────────────────────────────────\r\n\r\nexport interface ToolCallResult {\r\n allowed: boolean;\r\n output: string;\r\n requiresHumanReview: boolean;\r\n reviewId?: string;\r\n reason: string;\r\n}\r\n\r\n// ─── SecureTool ───────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * SecureTool wraps a tool function with Lelu's Confidence-Aware Auth gate.\r\n *\r\n * Implements the LangChain Tool interface (name + description + invoke)\r\n * so it can be dropped into any LangChain agent tool array:\r\n * ```typescript\r\n * const agent = await createOpenAIFunctionsAgent({ tools: [refundTool] });\r\n * ```\r\n */\r\nexport class SecureTool {\r\n readonly name: string;\r\n readonly description: string;\r\n\r\n private readonly opts: SecureToolOptions;\r\n\r\n constructor(opts: SecureToolOptions) {\r\n this.opts = opts;\r\n this.name = opts.name;\r\n this.description = opts.description;\r\n }\r\n\r\n /**\r\n * invoke — LangChain StructuredTool / DynamicTool compatible entry point.\r\n *\r\n * 1. Calls Lelu `agentAuthorize` with the confidence score\r\n * 2a. Allowed → runs the wrapped tool function\r\n * 2b. Requires human review → returns structured \"pending\" message\r\n * 2c. Denied → returns structured refusal string (LLM can self-correct)\r\n */\r\n async invoke(input: string): Promise<string> {\r\n const result = await this._check(input);\r\n if (result.allowed) {\r\n return result.output;\r\n }\r\n if (this.opts.throwOnDeny) {\r\n throw new Error(`[Lelu] Tool \"${this.name}\" denied: ${result.reason}`);\r\n }\r\n return result.output; // structured refusal or pending message\r\n }\r\n\r\n /** call — alias for older LangChain versions. */\r\n async call(input: string): Promise<string> {\r\n return this.invoke(input);\r\n }\r\n\r\n /**\r\n * Check authorization and run the tool if permitted.\r\n * Returns a full ToolCallResult for programmatic consumers.\r\n */\r\n async checkAndCall(input: string): Promise<ToolCallResult> {\r\n return this._check(input);\r\n }\r\n\r\n private async _check(input: string): Promise<ToolCallResult> {\r\n const { actor, requiredPermission, client, func, throwOnDeny } = this.opts;\r\n const confidence = this.opts.confidence ?? 1.0;\r\n const actingFor = this.opts.actingFor ?? \"\";\r\n\r\n let decision;\r\n try {\r\n decision = await client.agentAuthorize({\r\n actor,\r\n action: requiredPermission,\r\n context: {\r\n confidence,\r\n actingFor,\r\n },\r\n });\r\n } catch (err) {\r\n const msg = `[Lelu] Authorization check failed for \"${this.name}\": ${String(err)}`;\r\n if (throwOnDeny) throw new Error(msg);\r\n return {\r\n allowed: false,\r\n output: msg,\r\n requiresHumanReview: false,\r\n reason: String(err),\r\n };\r\n }\r\n\r\n // Human review required — queue and return pending message.\r\n if (decision.requiresHumanReview) {\r\n const msg =\r\n `[Lelu] Action \"${this.name}\" is queued for human review. ` +\r\n `Reason: ${decision.reason}. Please wait for approval before proceeding.`;\r\n return {\r\n allowed: false,\r\n output: msg,\r\n requiresHumanReview: true,\r\n reason: decision.reason,\r\n };\r\n }\r\n\r\n // Hard deny — return structured refusal.\r\n if (!decision.allowed) {\r\n const msg =\r\n `[Lelu] Action \"${this.name}\" was denied. ` +\r\n `Reason: ${decision.reason}. ` +\r\n `Downgraded scope: ${decision.downgradedScope ?? \"none\"}.`;\r\n return {\r\n allowed: false,\r\n output: msg,\r\n requiresHumanReview: false,\r\n reason: decision.reason,\r\n };\r\n }\r\n\r\n // Authorized — run the tool.\r\n const output = await func(input);\r\n return {\r\n allowed: true,\r\n output,\r\n requiresHumanReview: false,\r\n reason: decision.reason,\r\n };\r\n }\r\n}\r\n","import { OpenAI } from 'openai';\r\n\r\nexport class SemanticPolicyGenerator {\r\n private openai: OpenAI;\r\n\r\n constructor(apiKey: string) {\r\n this.openai = new OpenAI({ apiKey });\r\n }\r\n\r\n /**\r\n * Converts a natural language description into a deterministic Rego policy.\r\n * \r\n * @param description Natural language description of the policy (e.g., \"Don't let the bot refund more than $50 unless approved by a finance manager.\")\r\n * @param packageName The Rego package name (default: \"lelu.authz\")\r\n * @returns The generated Rego policy string\r\n */\r\n async generateRegoPolicy(description: string, packageName: string = \"lelu.authz\"): Promise<string> {\r\n const prompt = `\r\nYou are an expert in Open Policy Agent (OPA) Rego policies.\r\nYour task is to convert the following natural language description into a valid, deterministic Rego policy for the Lelu Auth Permission Engine.\r\n\r\nThe policy must output an object with the following structure:\r\n{\r\n \"allowed\": bool,\r\n \"reason\": string,\r\n \"downgraded_scope\": string (optional),\r\n \"requires_human_review\": bool (optional)\r\n}\r\n\r\nThe input to the policy will be an object with the following structure:\r\n{\r\n \"kind\": \"agent\" | \"human\",\r\n \"actor\": string,\r\n \"action\": string,\r\n \"resource\": map[string]any,\r\n \"confidence\": number (0.0 to 1.0),\r\n \"acting_for\": string,\r\n \"scope\": string\r\n}\r\n\r\nNatural Language Description:\r\n\"${description}\"\r\n\r\nPackage Name:\r\npackage ${packageName}\r\n\r\nRequirements:\r\n1. Output ONLY valid Rego code.\r\n2. Do not include markdown formatting (like \\`\\`\\`rego).\r\n3. Ensure the default state is deny (default allowed = false).\r\n4. Include comments explaining the logic.\r\n`;\r\n\r\n const response = await this.openai.chat.completions.create({\r\n model: \"gpt-4-turbo-preview\",\r\n messages: [\r\n { role: \"system\", content: \"You are a Rego policy generation assistant. Output only raw Rego code.\" },\r\n { role: \"user\", content: prompt }\r\n ],\r\n temperature: 0.1,\r\n });\r\n\r\n const regoCode = response.choices[0]?.message.content?.trim() || \"\";\r\n \r\n // Strip markdown code blocks if the LLM accidentally included them\r\n return regoCode.replace(/^```rego\\n/, '').replace(/\\n```$/, '');\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/langchain/secure-tool.ts","../../src/langchain/SemanticPolicyGenerator.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * SecureTool — LangChain tool wrapper with Confidence-Aware Auth\n *\n * Intercepts every tool call and gates it through the Lelu engine before\n * execution. Returns a structured refusal string when denied so the LLM can\n * self-correct, queue for human review, or escalate.\n *\n * Usage:\n * ```typescript\n * import { SecureTool } from 'lelu/langchain';\n *\n * const refundTool = new SecureTool({\n * name: 'process_refund',\n * description: 'Processes a customer refund',\n * actor: 'invoice_bot',\n * requiredPermission: 'invoice:refund',\n * client: leluClient,\n * func: async (input) => {\n * // your tool implementation\n * return `Refund processed for ${input}`;\n * },\n * });\n * ```\n */\n\nimport { LeluClient } from \"../client.js\";\n\n// ─── Minimal LangChain-compatible interface ───────────────────────────────────\n\n/** Minimal interface a wrapped tool must expose. */\nexport interface ToolLike {\n name: string;\n description: string;\n /** LangChain StructuredTool / DynamicTool use `invoke`. */\n invoke?: (input: string, ...args: unknown[]) => Promise<string>;\n /** Older LangChain versions use `call`. */\n call?: (input: string, ...args: unknown[]) => Promise<string>;\n}\n\n// ─── Options ──────────────────────────────────────────────────────────────────\n\nexport interface SecureToolOptions {\n /** Unique tool name (used as the action in authz request). */\n name: string;\n /** Human-readable description forwarded to the LLM. */\n description: string;\n /** The Lelu agent scope / actor name. */\n actor: string;\n /** The permission string being checked (e.g. \"invoice:refund\"). */\n requiredPermission: string;\n /** Configured LeluClient. */\n client: LeluClient;\n /** The actual tool function to execute when authorized. */\n func: (input: string) => Promise<string>;\n /**\n * Optional: LLM confidence score for this invocation (0.0–1.0).\n * If omitted, defaults to 1.0 (full confidence assumed).\n */\n confidence?: number;\n /**\n * Optional: the human user the agent is acting on behalf of.\n */\n actingFor?: string;\n /**\n * Optional: if true, throw an error when denied instead of returning\n * a structured refusal string. Default: false (silent fail, structured msg).\n */\n throwOnDeny?: boolean;\n}\n\n// ─── Result ───────────────────────────────────────────────────────────────────\n\nexport interface ToolCallResult {\n allowed: boolean;\n output: string;\n requiresHumanReview: boolean;\n reviewId?: string;\n reason: string;\n}\n\n// ─── SecureTool ───────────────────────────────────────────────────────────────\n\n/**\n * SecureTool wraps a tool function with Lelu's Confidence-Aware Auth gate.\n *\n * Implements the LangChain Tool interface (name + description + invoke)\n * so it can be dropped into any LangChain agent tool array:\n * ```typescript\n * const agent = await createOpenAIFunctionsAgent({ tools: [refundTool] });\n * ```\n */\nexport class SecureTool {\n readonly name: string;\n readonly description: string;\n\n private readonly opts: SecureToolOptions;\n\n constructor(opts: SecureToolOptions) {\n this.opts = opts;\n this.name = opts.name;\n this.description = opts.description;\n }\n\n /**\n * invoke — LangChain StructuredTool / DynamicTool compatible entry point.\n *\n * 1. Calls Lelu `agentAuthorize` with the confidence score\n * 2a. Allowed → runs the wrapped tool function\n * 2b. Requires human review → returns structured \"pending\" message\n * 2c. Denied → returns structured refusal string (LLM can self-correct)\n */\n async invoke(input: string): Promise<string> {\n const result = await this._check(input);\n if (result.allowed) {\n return result.output;\n }\n if (this.opts.throwOnDeny) {\n throw new Error(`[Lelu] Tool \"${this.name}\" denied: ${result.reason}`);\n }\n return result.output; // structured refusal or pending message\n }\n\n /** call — alias for older LangChain versions. */\n async call(input: string): Promise<string> {\n return this.invoke(input);\n }\n\n /**\n * Check authorization and run the tool if permitted.\n * Returns a full ToolCallResult for programmatic consumers.\n */\n async checkAndCall(input: string): Promise<ToolCallResult> {\n return this._check(input);\n }\n\n private async _check(input: string): Promise<ToolCallResult> {\n const { actor, requiredPermission, client, func, throwOnDeny } = this.opts;\n const confidence = this.opts.confidence ?? 1.0;\n const actingFor = this.opts.actingFor ?? \"\";\n\n let decision;\n try {\n decision = await client.agentAuthorize({\n actor,\n action: requiredPermission,\n context: {\n confidence,\n actingFor,\n },\n });\n } catch (err) {\n const msg = `[Lelu] Authorization check failed for \"${this.name}\": ${String(err)}`;\n if (throwOnDeny) throw new Error(msg);\n return {\n allowed: false,\n output: msg,\n requiresHumanReview: false,\n reason: String(err),\n };\n }\n\n // Human review required — queue and return pending message.\n if (decision.requiresHumanReview) {\n const msg =\n `[Lelu] Action \"${this.name}\" is queued for human review. ` +\n `Reason: ${decision.reason}. Please wait for approval before proceeding.`;\n return {\n allowed: false,\n output: msg,\n requiresHumanReview: true,\n reason: decision.reason,\n };\n }\n\n // Hard deny — return structured refusal.\n if (!decision.allowed) {\n const msg =\n `[Lelu] Action \"${this.name}\" was denied. ` +\n `Reason: ${decision.reason}. ` +\n `Downgraded scope: ${decision.downgradedScope ?? \"none\"}.`;\n return {\n allowed: false,\n output: msg,\n requiresHumanReview: false,\n reason: decision.reason,\n };\n }\n\n // Authorized — run the tool.\n const output = await func(input);\n return {\n allowed: true,\n output,\n requiresHumanReview: false,\n reason: decision.reason,\n };\n }\n}\n","import { OpenAI } from 'openai';\n\nexport class SemanticPolicyGenerator {\n private openai: OpenAI;\n\n constructor(apiKey: string) {\n this.openai = new OpenAI({ apiKey });\n }\n\n /**\n * Converts a natural language description into a deterministic Rego policy.\n * \n * @param description Natural language description of the policy (e.g., \"Don't let the bot refund more than $50 unless approved by a finance manager.\")\n * @param packageName The Rego package name (default: \"lelu.authz\")\n * @returns The generated Rego policy string\n */\n async generateRegoPolicy(description: string, packageName: string = \"lelu.authz\"): Promise<string> {\n const prompt = `\nYou are an expert in Open Policy Agent (OPA) Rego policies.\nYour task is to convert the following natural language description into a valid, deterministic Rego policy for the Lelu Auth Permission Engine.\n\nThe policy must output an object with the following structure:\n{\n \"allowed\": bool,\n \"reason\": string,\n \"downgraded_scope\": string (optional),\n \"requires_human_review\": bool (optional)\n}\n\nThe input to the policy will be an object with the following structure:\n{\n \"kind\": \"agent\" | \"human\",\n \"actor\": string,\n \"action\": string,\n \"resource\": map[string]any,\n \"confidence\": number (0.0 to 1.0),\n \"acting_for\": string,\n \"scope\": string\n}\n\nNatural Language Description:\n\"${description}\"\n\nPackage Name:\npackage ${packageName}\n\nRequirements:\n1. Output ONLY valid Rego code.\n2. Do not include markdown formatting (like \\`\\`\\`rego).\n3. Ensure the default state is deny (default allowed = false).\n4. Include comments explaining the logic.\n`;\n\n const response = await this.openai.chat.completions.create({\n model: \"gpt-4-turbo-preview\",\n messages: [\n { role: \"system\", content: \"You are a Rego policy generation assistant. Output only raw Rego code.\" },\n { role: \"user\", content: prompt }\n ],\n temperature: 0.1,\n });\n\n const regoCode = response.choices[0]?.message.content?.trim() || \"\";\n \n // Strip markdown code blocks if the LLM accidentally included them\n return regoCode.replace(/^```rego\\n/, '').replace(/\\n```$/, '');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/langchain/secure-tool.ts","../../src/langchain/SemanticPolicyGenerator.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * SecureTool — LangChain tool wrapper with Confidence-Aware Auth\r\n *\r\n * Intercepts every tool call and gates it through the Lelu engine before\r\n * execution. Returns a structured refusal string when denied so the LLM can\r\n * self-correct, queue for human review, or escalate.\r\n *\r\n * Usage:\r\n * ```typescript\r\n * import { SecureTool } from 'lelu/langchain';\r\n *\r\n * const refundTool = new SecureTool({\r\n * name: 'process_refund',\r\n * description: 'Processes a customer refund',\r\n * actor: 'invoice_bot',\r\n * requiredPermission: 'invoice:refund',\r\n * client: leluClient,\r\n * func: async (input) => {\r\n * // your tool implementation\r\n * return `Refund processed for ${input}`;\r\n * },\r\n * });\r\n * ```\r\n */\r\n\r\nimport { LeluClient } from \"../client.js\";\r\n\r\n// ─── Minimal LangChain-compatible interface ───────────────────────────────────\r\n\r\n/** Minimal interface a wrapped tool must expose. */\r\nexport interface ToolLike {\r\n name: string;\r\n description: string;\r\n /** LangChain StructuredTool / DynamicTool use `invoke`. */\r\n invoke?: (input: string, ...args: unknown[]) => Promise<string>;\r\n /** Older LangChain versions use `call`. */\r\n call?: (input: string, ...args: unknown[]) => Promise<string>;\r\n}\r\n\r\n// ─── Options ──────────────────────────────────────────────────────────────────\r\n\r\nexport interface SecureToolOptions {\r\n /** Unique tool name (used as the action in authz request). */\r\n name: string;\r\n /** Human-readable description forwarded to the LLM. */\r\n description: string;\r\n /** The Lelu agent scope / actor name. */\r\n actor: string;\r\n /** The permission string being checked (e.g. \"invoice:refund\"). */\r\n requiredPermission: string;\r\n /** Configured LeluClient. */\r\n client: LeluClient;\r\n /** The actual tool function to execute when authorized. */\r\n func: (input: string) => Promise<string>;\r\n /**\r\n * Optional: LLM confidence score for this invocation (0.0–1.0).\r\n * If omitted, defaults to 1.0 (full confidence assumed).\r\n */\r\n confidence?: number;\r\n /**\r\n * Optional: the human user the agent is acting on behalf of.\r\n */\r\n actingFor?: string;\r\n /**\r\n * Optional: if true, throw an error when denied instead of returning\r\n * a structured refusal string. Default: false (silent fail, structured msg).\r\n */\r\n throwOnDeny?: boolean;\r\n}\r\n\r\n// ─── Result ───────────────────────────────────────────────────────────────────\r\n\r\nexport interface ToolCallResult {\r\n allowed: boolean;\r\n output: string;\r\n requiresHumanReview: boolean;\r\n reviewId?: string;\r\n reason: string;\r\n}\r\n\r\n// ─── SecureTool ───────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * SecureTool wraps a tool function with Lelu's Confidence-Aware Auth gate.\r\n *\r\n * Implements the LangChain Tool interface (name + description + invoke)\r\n * so it can be dropped into any LangChain agent tool array:\r\n * ```typescript\r\n * const agent = await createOpenAIFunctionsAgent({ tools: [refundTool] });\r\n * ```\r\n */\r\nexport class SecureTool {\r\n readonly name: string;\r\n readonly description: string;\r\n\r\n private readonly opts: SecureToolOptions;\r\n\r\n constructor(opts: SecureToolOptions) {\r\n this.opts = opts;\r\n this.name = opts.name;\r\n this.description = opts.description;\r\n }\r\n\r\n /**\r\n * invoke — LangChain StructuredTool / DynamicTool compatible entry point.\r\n *\r\n * 1. Calls Lelu `agentAuthorize` with the confidence score\r\n * 2a. Allowed → runs the wrapped tool function\r\n * 2b. Requires human review → returns structured \"pending\" message\r\n * 2c. Denied → returns structured refusal string (LLM can self-correct)\r\n */\r\n async invoke(input: string): Promise<string> {\r\n const result = await this._check(input);\r\n if (result.allowed) {\r\n return result.output;\r\n }\r\n if (this.opts.throwOnDeny) {\r\n throw new Error(`[Lelu] Tool \"${this.name}\" denied: ${result.reason}`);\r\n }\r\n return result.output; // structured refusal or pending message\r\n }\r\n\r\n /** call — alias for older LangChain versions. */\r\n async call(input: string): Promise<string> {\r\n return this.invoke(input);\r\n }\r\n\r\n /**\r\n * Check authorization and run the tool if permitted.\r\n * Returns a full ToolCallResult for programmatic consumers.\r\n */\r\n async checkAndCall(input: string): Promise<ToolCallResult> {\r\n return this._check(input);\r\n }\r\n\r\n private async _check(input: string): Promise<ToolCallResult> {\r\n const { actor, requiredPermission, client, func, throwOnDeny } = this.opts;\r\n const confidence = this.opts.confidence ?? 1.0;\r\n const actingFor = this.opts.actingFor ?? \"\";\r\n\r\n let decision;\r\n try {\r\n decision = await client.agentAuthorize({\r\n actor,\r\n action: requiredPermission,\r\n context: {\r\n confidence,\r\n actingFor,\r\n },\r\n });\r\n } catch (err) {\r\n const msg = `[Lelu] Authorization check failed for \"${this.name}\": ${String(err)}`;\r\n if (throwOnDeny) throw new Error(msg);\r\n return {\r\n allowed: false,\r\n output: msg,\r\n requiresHumanReview: false,\r\n reason: String(err),\r\n };\r\n }\r\n\r\n // Human review required — queue and return pending message.\r\n if (decision.requiresHumanReview) {\r\n const msg =\r\n `[Lelu] Action \"${this.name}\" is queued for human review. ` +\r\n `Reason: ${decision.reason}. Please wait for approval before proceeding.`;\r\n return {\r\n allowed: false,\r\n output: msg,\r\n requiresHumanReview: true,\r\n reason: decision.reason,\r\n };\r\n }\r\n\r\n // Hard deny — return structured refusal.\r\n if (!decision.allowed) {\r\n const msg =\r\n `[Lelu] Action \"${this.name}\" was denied. ` +\r\n `Reason: ${decision.reason}. ` +\r\n `Downgraded scope: ${decision.downgradedScope ?? \"none\"}.`;\r\n return {\r\n allowed: false,\r\n output: msg,\r\n requiresHumanReview: false,\r\n reason: decision.reason,\r\n };\r\n }\r\n\r\n // Authorized — run the tool.\r\n const output = await func(input);\r\n return {\r\n allowed: true,\r\n output,\r\n requiresHumanReview: false,\r\n reason: decision.reason,\r\n };\r\n }\r\n}\r\n","import { OpenAI } from 'openai';\r\n\r\nexport class SemanticPolicyGenerator {\r\n private openai: OpenAI;\r\n\r\n constructor(apiKey: string) {\r\n this.openai = new OpenAI({ apiKey });\r\n }\r\n\r\n /**\r\n * Converts a natural language description into a deterministic Rego policy.\r\n * \r\n * @param description Natural language description of the policy (e.g., \"Don't let the bot refund more than $50 unless approved by a finance manager.\")\r\n * @param packageName The Rego package name (default: \"lelu.authz\")\r\n * @returns The generated Rego policy string\r\n */\r\n async generateRegoPolicy(description: string, packageName: string = \"lelu.authz\"): Promise<string> {\r\n const prompt = `\r\nYou are an expert in Open Policy Agent (OPA) Rego policies.\r\nYour task is to convert the following natural language description into a valid, deterministic Rego policy for the Lelu Auth Permission Engine.\r\n\r\nThe policy must output an object with the following structure:\r\n{\r\n \"allowed\": bool,\r\n \"reason\": string,\r\n \"downgraded_scope\": string (optional),\r\n \"requires_human_review\": bool (optional)\r\n}\r\n\r\nThe input to the policy will be an object with the following structure:\r\n{\r\n \"kind\": \"agent\" | \"human\",\r\n \"actor\": string,\r\n \"action\": string,\r\n \"resource\": map[string]any,\r\n \"confidence\": number (0.0 to 1.0),\r\n \"acting_for\": string,\r\n \"scope\": string\r\n}\r\n\r\nNatural Language Description:\r\n\"${description}\"\r\n\r\nPackage Name:\r\npackage ${packageName}\r\n\r\nRequirements:\r\n1. Output ONLY valid Rego code.\r\n2. Do not include markdown formatting (like \\`\\`\\`rego).\r\n3. Ensure the default state is deny (default allowed = false).\r\n4. Include comments explaining the logic.\r\n`;\r\n\r\n const response = await this.openai.chat.completions.create({\r\n model: \"gpt-4-turbo-preview\",\r\n messages: [\r\n { role: \"system\", content: \"You are a Rego policy generation assistant. Output only raw Rego code.\" },\r\n { role: \"user\", content: prompt }\r\n ],\r\n temperature: 0.1,\r\n });\r\n\r\n const regoCode = response.choices[0]?.message.content?.trim() || \"\";\r\n \r\n // Strip markdown code blocks if the LLM accidentally included them\r\n return regoCode.replace(/^```rego\\n/, '').replace(/\\n```$/, '');\r\n }\r\n}\r\n"]}
|
package/dist/react/index.js
CHANGED
|
@@ -52,7 +52,8 @@ var LeluClient = class {
|
|
|
52
52
|
timeoutMs;
|
|
53
53
|
apiKey;
|
|
54
54
|
constructor(cfg = {}) {
|
|
55
|
-
|
|
55
|
+
const envBaseUrl = typeof process !== "undefined" && process.env ? process.env["LELU_BASE_URL"] : void 0;
|
|
56
|
+
this.baseUrl = (cfg.baseUrl ?? envBaseUrl ?? "http://localhost:8080").replace(/\/$/, "");
|
|
56
57
|
this.timeoutMs = cfg.timeoutMs ?? 5e3;
|
|
57
58
|
this.apiKey = cfg.apiKey;
|
|
58
59
|
}
|