@logickernel/bridge 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,276 @@
1
+ # Bridge
2
+
3
+ Framework-agnostic micro-frontend authentication library for AuthJS/NextAuth JWT tokens.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @logickernel/bridge
9
+ # or
10
+ pnpm add @logickernel/bridge
11
+ # or
12
+ yarn add @logickernel/bridge
13
+ ```
14
+
15
+ ## Features
16
+
17
+ - **Framework-agnostic core** - JWT decoding and validation works anywhere
18
+ - **Next.js adapter** - First-class support for Next.js App Router
19
+ - **Role-based access control** - Check user roles against organization permissions
20
+ - **TypeScript-first** - Full type safety with detailed type exports
21
+ - **Dual ESM/CJS** - Works in any JavaScript environment
22
+
23
+ ## Quick Start
24
+
25
+ ### Environment Variables
26
+
27
+ ```bash
28
+ AUTH_SECRET=your-nextauth-secret # Required: Same secret used by your kernel/auth server
29
+ AUTH_URL=http://localhost:3000 # Required: Used internally for API calls to the kernel
30
+ BASE_URL=http://localhost:7001 # Optional: Facade URL for user-facing redirects (used by getBaseUrl())
31
+ AUTH_COOKIE=authjs.session-token # Optional: Cookie name for session token (defaults to authjs.session-token)
32
+ ```
33
+
34
+ ### Core Usage (Framework-Agnostic)
35
+
36
+ ```typescript
37
+ import {
38
+ decodeSessionToken,
39
+ extractSessionCookie,
40
+ fetchUserRoles,
41
+ hasAnyRole,
42
+ } from "@logickernel/bridge"
43
+
44
+ // Decode a JWT session token
45
+ const result = await decodeSessionToken(token, secret, isSecure)
46
+ if (result.success) {
47
+ console.log(result.session.user.email)
48
+ console.log(result.session.user.id)
49
+ } else {
50
+ console.error(result.error) // "missing_token" | "missing_secret" | "decode_error" | "expired"
51
+ }
52
+
53
+ // Check user roles (uses AUTH_URL environment variable internally)
54
+ // User ID is determined from the session token
55
+ const roles = await fetchUserRoles({
56
+ organizationId: "org-456",
57
+ sessionToken: token,
58
+ })
59
+
60
+ if (roles.success && hasAnyRole(roles.roles, ["organization.owner"])) {
61
+ // User is an owner
62
+ }
63
+ ```
64
+
65
+ ### Next.js Usage
66
+
67
+ ```typescript
68
+ import {
69
+ getSession,
70
+ getUserRoles,
71
+ withAuth,
72
+ checkPageAuth,
73
+ createProxyHandler,
74
+ } from "@logickernel/bridge/next"
75
+ ```
76
+
77
+ #### Server Components / Pages
78
+
79
+ ```typescript
80
+ // app/dashboard/page.tsx
81
+ import { getSession } from "@logickernel/bridge/next"
82
+ import { redirect } from "next/navigation"
83
+
84
+ export default async function DashboardPage() {
85
+ const session = await getSession()
86
+
87
+ if (!session) {
88
+ redirect("/auth/signin")
89
+ }
90
+
91
+ return <div>Welcome, {session.user.email}!</div>
92
+ }
93
+ ```
94
+
95
+ #### Role-Based Page Protection
96
+
97
+ ```typescript
98
+ // app/[org_id]/admin/page.tsx
99
+ import { checkPageAuth } from "@logickernel/bridge/next"
100
+ import { redirect, notFound } from "next/navigation"
101
+
102
+ export default async function AdminPage({
103
+ params,
104
+ }: {
105
+ params: Promise<{ org_id: string }>
106
+ }) {
107
+ const { org_id } = await params
108
+
109
+ const auth = await checkPageAuth({
110
+ requiredRoles: ["organization.owner", "organization.editor"],
111
+ organizationId: org_id,
112
+ })
113
+
114
+ if (!auth.authenticated) {
115
+ redirect(auth.redirectUrl)
116
+ }
117
+
118
+ // User is authenticated but may not have required roles
119
+ if (!auth.roles.some(r => ["organization.owner", "organization.editor"].includes(r))) {
120
+ notFound()
121
+ }
122
+
123
+ return <div>Admin Panel for {session.user.email}</div>
124
+ }
125
+ ```
126
+
127
+ #### API Routes
128
+
129
+ ```typescript
130
+ // app/api/data/route.ts
131
+ import { withAuth } from "@logickernel/bridge/next"
132
+ import { NextResponse } from "next/server"
133
+
134
+ // Any authenticated user
135
+ export const GET = withAuth(async (request, { session }) => {
136
+ return NextResponse.json({
137
+ userId: session.user.id,
138
+ email: session.user.email,
139
+ })
140
+ })
141
+
142
+ // With role requirements
143
+ export const DELETE = withAuth(
144
+ async (request, { session }) => {
145
+ // Only owners can delete
146
+ return NextResponse.json({ deleted: true })
147
+ },
148
+ {
149
+ requiredRoles: ["organization.owner"],
150
+ organizationId: "org_id", // Extract from route params
151
+ }
152
+ )
153
+ ```
154
+
155
+ #### Middleware / Proxy
156
+
157
+ ```typescript
158
+ // src/proxy.ts (or middleware.ts)
159
+ import { createProxyHandler, type ProxyOptions } from "@logickernel/bridge/next"
160
+
161
+ const config: ProxyOptions = {
162
+ basePath: "/app",
163
+ protectedRoutes: {
164
+ "/app/dashboard": [], // Any authenticated user
165
+ "/app/settings": [],
166
+ },
167
+ dynamicRoutes: [
168
+ {
169
+ pattern: "/[organization_id]/admin",
170
+ requiredRoles: ["organization.owner"],
171
+ },
172
+ ],
173
+ }
174
+
175
+ export const proxy = createProxyHandler(config)
176
+
177
+ // Static config for Next.js (must be in the same file)
178
+ export const middlewareConfig = {
179
+ matcher: ["/((?!_next/static|_next/image|favicon.ico|public).*)"],
180
+ }
181
+ ```
182
+
183
+ ## API Reference
184
+
185
+ ### Core Exports (`@logickernel/bridge`)
186
+
187
+ | Export | Description |
188
+ |--------|-------------|
189
+ | `decodeSessionToken(token, secret, isSecure)` | Decode and validate a JWT session token |
190
+ | `extractSessionCookie(cookies)` | Extract session cookie from a cookies object |
191
+ | `fetchUserRoles(options)` | Fetch user roles from the kernel API (uses AUTH_URL internally) |
192
+ | `hasAnyRole(userRoles, requiredRoles)` | Check if user has at least one required role |
193
+ | `hasAllRoles(userRoles, requiredRoles)` | Check if user has all required roles |
194
+ | `hasRole(userRoles, role)` | Check if user has a specific role |
195
+ | `matchRoute(pathname, config)` | Match a pathname against route configuration |
196
+ | `buildSignInUrl(callbackUrl?)` | Build a sign-in redirect URL (uses AUTH_URL internally) |
197
+ | `buildSignOutUrl(callbackUrl?)` | Build a sign-out redirect URL (uses AUTH_URL internally) |
198
+
199
+ ### Next.js Exports (`@logickernel/bridge/next`)
200
+
201
+ | Export | Description |
202
+ |--------|-------------|
203
+ | `getSession()` | Get the current session from cookies |
204
+ | `getSessionToken()` | Get the raw session token value |
205
+ | `getUserRoles(orgId)` | Get user roles in an organization (user ID determined from session token) |
206
+ | `withAuth(handler, options?)` | Wrap an API route with authentication |
207
+ | `getSessionFromRequest(request)` | Get session from a NextRequest |
208
+ | `checkPageAuth(options?)` | Check authentication for a page |
209
+ | `requireAuth()` | Require authentication (throws if not authenticated) |
210
+ | `hasRequiredRole(orgId, roles)` | Check if user has required roles (user ID determined from session token) |
211
+ | `createProxyHandler(options)` | Create a middleware/proxy handler |
212
+
213
+ ### Types
214
+
215
+ ```typescript
216
+ import type {
217
+ Session,
218
+ SessionUser,
219
+ DecodeResult,
220
+ RouteConfig,
221
+ RouteMatch,
222
+ MicroFrontendConfig,
223
+ } from "@logickernel/bridge"
224
+
225
+ import type {
226
+ ProxyOptions,
227
+ DynamicRoutePattern,
228
+ AuthContext,
229
+ AuthenticatedHandler,
230
+ WithAuthOptions,
231
+ PageAuthOptions,
232
+ PageAuthResult,
233
+ } from "@logickernel/bridge/next"
234
+ ```
235
+
236
+ ## Architecture
237
+
238
+ ```
239
+ bridge/
240
+ ├── src/
241
+ │ ├── index.ts # Core exports
242
+ │ ├── types.ts # Core type definitions
243
+ │ ├── jwt.ts # JWT decoding utilities
244
+ │ ├── roles.ts # Role checking utilities
245
+ │ ├── routes.ts # Route matching utilities
246
+ │ └── next/
247
+ │ ├── index.ts # Next.js adapter exports
248
+ │ ├── types.ts # Next.js-specific types
249
+ │ ├── session.ts # Session utilities
250
+ │ ├── api.ts # API route utilities
251
+ │ ├── page.ts # Page utilities
252
+ │ └── proxy.ts # Middleware/proxy utilities
253
+ ```
254
+
255
+ ## Development
256
+
257
+ ```bash
258
+ # Install dependencies
259
+ npm install
260
+
261
+ # Build the library
262
+ npm run build
263
+
264
+ # Watch mode for development
265
+ npm run dev
266
+
267
+ # Type checking
268
+ npm run typecheck
269
+
270
+ # Clean build artifacts
271
+ npm run clean
272
+ ```
273
+
274
+ ## License
275
+
276
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,193 @@
1
+ 'use strict';
2
+
3
+ var jwt = require('@auth/core/jwt');
4
+
5
+ // src/jwt.ts
6
+ function getBaseCookieName() {
7
+ const cookieName = process.env.AUTH_COOKIE || "authjs.session-token";
8
+ return cookieName.startsWith("__Secure-") ? cookieName.slice(10) : cookieName;
9
+ }
10
+ var COOKIE_NAMES = {
11
+ get secure() {
12
+ const baseName = getBaseCookieName();
13
+ return `__Secure-${baseName}`;
14
+ },
15
+ get dev() {
16
+ return getBaseCookieName();
17
+ }
18
+ };
19
+ function getAuthUrl() {
20
+ return process.env.AUTH_URL || process.env.BASE_URL || "http://localhost:3000";
21
+ }
22
+ function getSalt(isSecure) {
23
+ return isSecure ? COOKIE_NAMES.secure : COOKIE_NAMES.dev;
24
+ }
25
+ function getCookieName(isSecure) {
26
+ return isSecure ? COOKIE_NAMES.secure : COOKIE_NAMES.dev;
27
+ }
28
+ function isTokenExpired(decoded) {
29
+ if (!decoded.exp) return false;
30
+ return decoded.exp * 1e3 < Date.now();
31
+ }
32
+ function mapToSession(decoded) {
33
+ return {
34
+ user: {
35
+ id: decoded.sub,
36
+ email: decoded.email,
37
+ name: decoded.name || null,
38
+ image: decoded.picture || null
39
+ },
40
+ expires: decoded.exp ? new Date(decoded.exp * 1e3).toISOString() : new Date(Date.now() + 30 * 24 * 60 * 60 * 1e3).toISOString()
41
+ // Default 30 days
42
+ };
43
+ }
44
+ async function decodeSessionToken(token, secret, isSecure = false) {
45
+ if (!token) {
46
+ return { success: false, error: "missing_token" };
47
+ }
48
+ if (!secret) {
49
+ return { success: false, error: "missing_secret" };
50
+ }
51
+ try {
52
+ const salt = getSalt(isSecure);
53
+ const decoded = await jwt.decode({ token, secret, salt });
54
+ if (!decoded) {
55
+ return { success: false, error: "decode_error" };
56
+ }
57
+ if (isTokenExpired(decoded)) {
58
+ return { success: false, error: "expired" };
59
+ }
60
+ const session = mapToSession(decoded);
61
+ return {
62
+ success: true,
63
+ session,
64
+ decoded
65
+ };
66
+ } catch {
67
+ return { success: false, error: "decode_error" };
68
+ }
69
+ }
70
+ function extractSessionCookie(cookies) {
71
+ const secureCookie = cookies.get(COOKIE_NAMES.secure);
72
+ if (secureCookie?.value) {
73
+ return { value: secureCookie.value, isSecure: true };
74
+ }
75
+ const devCookie = cookies.get(COOKIE_NAMES.dev);
76
+ if (devCookie?.value) {
77
+ return { value: devCookie.value, isSecure: false };
78
+ }
79
+ return void 0;
80
+ }
81
+
82
+ // src/roles.ts
83
+ async function fetchUserRoles(options) {
84
+ const { organizationId, sessionToken, fetchFn = fetch } = options;
85
+ const isSecure = options.isSecure ?? process.env.NODE_ENV === "production";
86
+ const kernelUrl = getAuthUrl();
87
+ const cookieName = getCookieName(isSecure);
88
+ try {
89
+ const response = await fetchFn(
90
+ `${kernelUrl}/api/user/organizations/${organizationId}/roles`,
91
+ {
92
+ headers: {
93
+ Cookie: `${cookieName}=${sessionToken}`
94
+ },
95
+ cache: "no-store"
96
+ }
97
+ );
98
+ if (!response.ok) {
99
+ return {
100
+ success: false,
101
+ error: `Failed to fetch roles: ${response.status}`
102
+ };
103
+ }
104
+ const data = await response.json();
105
+ const roles = data.roles?.map((r) => r.roleName) || [];
106
+ return { success: true, roles };
107
+ } catch (error) {
108
+ return {
109
+ success: false,
110
+ error: error instanceof Error ? error.message : "Unknown error"
111
+ };
112
+ }
113
+ }
114
+ function hasAnyRole(userRoles, requiredRoles) {
115
+ if (requiredRoles.length === 0) return true;
116
+ return requiredRoles.some((role) => userRoles.includes(role));
117
+ }
118
+ function hasAllRoles(userRoles, requiredRoles) {
119
+ if (requiredRoles.length === 0) return true;
120
+ return requiredRoles.every((role) => userRoles.includes(role));
121
+ }
122
+ function hasRole(userRoles, role) {
123
+ return userRoles.includes(role);
124
+ }
125
+
126
+ // src/routes.ts
127
+ function matchesAnyRoute(pathname, routes) {
128
+ return routes.some((route) => pathname.startsWith(route));
129
+ }
130
+ function findMatchingProtectedRoute(pathname, protectedRoutes) {
131
+ for (const [route, roles] of Object.entries(protectedRoutes)) {
132
+ if (pathname.startsWith(route)) {
133
+ return { route, requiredRoles: roles };
134
+ }
135
+ }
136
+ return void 0;
137
+ }
138
+ function matchRoute(pathname, config) {
139
+ if (config.publicRoutes && matchesAnyRoute(pathname, config.publicRoutes)) {
140
+ return { type: "public" };
141
+ }
142
+ const match = findMatchingProtectedRoute(pathname, config.protectedRoutes);
143
+ if (match) {
144
+ return { type: "protected", requiredRoles: match.requiredRoles };
145
+ }
146
+ return { type: "unprotected" };
147
+ }
148
+ function createConfig(options) {
149
+ return {
150
+ basePath: options.basePath,
151
+ protectedRoutes: options.protectedRoutes || {
152
+ "/dashboard": [],
153
+ "/admin": ["organization.owner"]
154
+ },
155
+ publicRoutes: options.publicRoutes || []
156
+ };
157
+ }
158
+ function buildSignInUrl(callbackUrl) {
159
+ const authUrl = getAuthUrl();
160
+ const url = new URL("/auth/signin", authUrl);
161
+ if (callbackUrl) {
162
+ url.searchParams.set("callbackUrl", callbackUrl);
163
+ }
164
+ return url;
165
+ }
166
+ function buildSignOutUrl(callbackUrl) {
167
+ const authUrl = getAuthUrl();
168
+ const url = new URL("/auth/signout", authUrl);
169
+ if (callbackUrl) {
170
+ url.searchParams.set("callbackUrl", callbackUrl);
171
+ }
172
+ return url;
173
+ }
174
+
175
+ exports.COOKIE_NAMES = COOKIE_NAMES;
176
+ exports.buildSignInUrl = buildSignInUrl;
177
+ exports.buildSignOutUrl = buildSignOutUrl;
178
+ exports.createConfig = createConfig;
179
+ exports.decodeSessionToken = decodeSessionToken;
180
+ exports.extractSessionCookie = extractSessionCookie;
181
+ exports.fetchUserRoles = fetchUserRoles;
182
+ exports.findMatchingProtectedRoute = findMatchingProtectedRoute;
183
+ exports.getCookieName = getCookieName;
184
+ exports.getSalt = getSalt;
185
+ exports.hasAllRoles = hasAllRoles;
186
+ exports.hasAnyRole = hasAnyRole;
187
+ exports.hasRole = hasRole;
188
+ exports.isTokenExpired = isTokenExpired;
189
+ exports.mapToSession = mapToSession;
190
+ exports.matchRoute = matchRoute;
191
+ exports.matchesAnyRoute = matchesAnyRoute;
192
+ //# sourceMappingURL=index.cjs.map
193
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/jwt.ts","../src/roles.ts","../src/routes.ts"],"names":["decode"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Kernel Bridge JWT\n * Framework-agnostic JWT decoding for AuthJS/NextAuth tokens\n */\n\nimport { decode } from \"@auth/core/jwt\"\nimport type { Session, SessionCookie, DecodeResult, DecodedToken } from \"./types\"\n\n/**\n * Get the base cookie name from AUTH_COOKIE env var or default to authjs.session-token\n * Strips __Secure- prefix if present, as it will be added automatically for secure cookies\n */\nfunction getBaseCookieName(): string {\n const cookieName = process.env.AUTH_COOKIE || \"authjs.session-token\"\n // Remove __Secure- prefix if present, as we'll add it back for secure cookies\n return cookieName.startsWith(\"__Secure-\") ? cookieName.slice(10) : cookieName\n}\n\n/**\n * Cookie names used by AuthJS/NextAuth\n * Defaults to authjs.session-token, can be overridden via AUTH_COOKIE env var\n */\nexport const COOKIE_NAMES = {\n get secure(): string {\n const baseName = getBaseCookieName()\n // Secure cookies must start with __Secure- prefix\n return `__Secure-${baseName}`\n },\n get dev(): string {\n return getBaseCookieName()\n },\n} as const\n\n/**\n * Get the AUTH_URL from environment variables\n * This is used internally for API calls to the kernel\n */\nexport function getAuthUrl(): string {\n return process.env.AUTH_URL || process.env.BASE_URL || \"http://localhost:3000\"\n}\n\n/**\n * Get the appropriate salt for JWT decoding based on cookie type\n */\nexport function getSalt(isSecure: boolean): string {\n return isSecure ? COOKIE_NAMES.secure : COOKIE_NAMES.dev\n}\n\n/**\n * Get the cookie name based on security mode\n */\nexport function getCookieName(isSecure: boolean): string {\n return isSecure ? COOKIE_NAMES.secure : COOKIE_NAMES.dev\n}\n\n/**\n * Check if a token is expired\n */\nexport function isTokenExpired(decoded: DecodedToken): boolean {\n if (!decoded.exp) return false\n return decoded.exp * 1000 < Date.now()\n}\n\n/**\n * Map decoded JWT payload to Session structure\n */\nexport function mapToSession(decoded: DecodedToken): Session {\n return {\n user: {\n id: decoded.sub as string,\n email: decoded.email as string,\n name: (decoded.name as string) || null,\n image: (decoded.picture as string) || null,\n },\n expires: decoded.exp\n ? new Date(decoded.exp * 1000).toISOString()\n : new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), // Default 30 days\n }\n}\n\n/**\n * Decode and validate a session token\n *\n * This is the core function - framework-agnostic JWT decoding.\n * The caller is responsible for extracting the token from their framework's\n * cookie/header mechanism.\n *\n * @param token - The JWT session token\n * @param secret - The AUTH_SECRET used to sign the token\n * @param isSecure - Whether the token came from a secure cookie\n * @returns DecodeResult with session data or error\n *\n * @example\n * ```typescript\n * const result = await decodeSessionToken(token, process.env.AUTH_SECRET, isSecure)\n * if (result.success) {\n * console.log(result.session.user.email)\n * } else {\n * console.error(result.error)\n * }\n * ```\n */\nexport async function decodeSessionToken(\n token: string | undefined,\n secret: string | undefined,\n isSecure: boolean = false\n): Promise<DecodeResult> {\n if (!token) {\n return { success: false, error: \"missing_token\" }\n }\n\n if (!secret) {\n return { success: false, error: \"missing_secret\" }\n }\n\n try {\n const salt = getSalt(isSecure)\n const decoded = await decode({ token, secret, salt })\n\n if (!decoded) {\n return { success: false, error: \"decode_error\" }\n }\n\n if (isTokenExpired(decoded as DecodedToken)) {\n return { success: false, error: \"expired\" }\n }\n\n const session = mapToSession(decoded as DecodedToken)\n return {\n success: true,\n session,\n decoded: decoded as DecodedToken,\n }\n } catch {\n return { success: false, error: \"decode_error\" }\n }\n}\n\n/**\n * Extract session cookie from a cookies object (generic interface)\n *\n * This works with any object that has a `get(name)` method returning\n * `{ value: string } | undefined`, like Next.js cookies() or similar.\n *\n * @param cookies - Object with get(name) method\n * @returns SessionCookie or undefined if no session cookie found\n */\nexport function extractSessionCookie(cookies: {\n get(name: string): { value: string } | undefined\n}): SessionCookie | undefined {\n // Try secure cookie first (production with HTTPS)\n const secureCookie = cookies.get(COOKIE_NAMES.secure)\n if (secureCookie?.value) {\n return { value: secureCookie.value, isSecure: true }\n }\n\n // Fall back to non-secure cookie (development)\n const devCookie = cookies.get(COOKIE_NAMES.dev)\n if (devCookie?.value) {\n return { value: devCookie.value, isSecure: false }\n }\n\n return undefined\n}\n","/**\n * Kernel Bridge Roles\n * Role checking and permission utilities\n */\n\nimport { getCookieName, getAuthUrl } from \"./jwt\"\n\n/**\n * Options for fetching user roles from the kernel\n */\nexport interface FetchRolesOptions {\n /**\n * Organization ID to fetch roles in\n */\n organizationId: string\n\n /**\n * Session token for authentication (user ID is determined from the token)\n */\n sessionToken: string\n\n /**\n * Whether using secure cookie\n * Defaults to NODE_ENV === \"production\" if not provided\n */\n isSecure?: boolean\n\n /**\n * Custom fetch function (optional, for testing or SSR)\n */\n fetchFn?: typeof fetch\n}\n\n/**\n * Result of role fetching operation\n */\nexport type FetchRolesResult =\n | { success: true; roles: string[] }\n | { success: false; error: string }\n\n/**\n * Fetch user roles from the kernel API\n *\n * This is a framework-agnostic function that makes a fetch request\n * to the kernel's roles endpoint. Uses AUTH_URL environment variable internally.\n * The user ID is determined from the session token.\n *\n * @param options - Configuration for fetching roles\n * @returns Promise with roles array or error\n *\n * @example\n * ```typescript\n * const result = await fetchUserRoles({\n * organizationId: \"org-123\",\n * sessionToken: token,\n * // isSecure defaults to NODE_ENV === \"production\"\n * })\n * if (result.success) {\n * console.log(result.roles)\n * }\n * ```\n */\nexport async function fetchUserRoles(\n options: FetchRolesOptions\n): Promise<FetchRolesResult> {\n const { organizationId, sessionToken, fetchFn = fetch } = options\n // Default isSecure to production mode\n const isSecure = options.isSecure ?? (process.env.NODE_ENV === \"production\")\n const kernelUrl = getAuthUrl()\n const cookieName = getCookieName(isSecure)\n\n try {\n const response = await fetchFn(\n `${kernelUrl}/api/user/organizations/${organizationId}/roles`,\n {\n headers: {\n Cookie: `${cookieName}=${sessionToken}`,\n },\n cache: \"no-store\",\n }\n )\n\n if (!response.ok) {\n return {\n success: false,\n error: `Failed to fetch roles: ${response.status}`,\n }\n }\n\n const data = await response.json()\n const roles = data.roles?.map((r: { roleName: string }) => r.roleName) || []\n\n return { success: true, roles }\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n }\n }\n}\n\n/**\n * Check if user has at least one of the required roles\n */\nexport function hasAnyRole(userRoles: string[], requiredRoles: string[]): boolean {\n if (requiredRoles.length === 0) return true // No roles required = any authenticated user\n return requiredRoles.some((role) => userRoles.includes(role))\n}\n\n/**\n * Check if user has all of the required roles\n */\nexport function hasAllRoles(userRoles: string[], requiredRoles: string[]): boolean {\n if (requiredRoles.length === 0) return true\n return requiredRoles.every((role) => userRoles.includes(role))\n}\n\n/**\n * Check if user has a specific role\n */\nexport function hasRole(userRoles: string[], role: string): boolean {\n return userRoles.includes(role)\n}\n\n","/**\n * Kernel Bridge Routes\n * Route matching and protection utilities\n */\n\nimport { getAuthUrl } from \"./jwt\"\nimport type { RouteConfig, RouteMatch, MicroFrontendConfig } from \"./types\"\n\n/**\n * Check if a pathname matches any route in the list\n */\nexport function matchesAnyRoute(pathname: string, routes: string[]): boolean {\n return routes.some((route) => pathname.startsWith(route))\n}\n\n/**\n * Find the first matching protected route for a pathname\n */\nexport function findMatchingProtectedRoute(\n pathname: string,\n protectedRoutes: RouteConfig\n): { route: string; requiredRoles: string[] } | undefined {\n for (const [route, roles] of Object.entries(protectedRoutes)) {\n if (pathname.startsWith(route)) {\n return { route, requiredRoles: roles }\n }\n }\n return undefined\n}\n\n/**\n * Match a pathname against route configuration\n *\n * @param pathname - The URL pathname to match\n * @param config - Micro-frontend configuration\n * @returns RouteMatch indicating the type of route\n *\n * @example\n * ```typescript\n * const match = matchRoute(\"/dashboard\", {\n * publicRoutes: [\"/\", \"/api/health\"],\n * protectedRoutes: { \"/dashboard\": [], \"/admin\": [\"organization.owner\"] },\n * })\n * // Returns: { type: \"protected\", requiredRoles: [] }\n * ```\n */\nexport function matchRoute(\n pathname: string,\n config: Pick<MicroFrontendConfig, \"publicRoutes\" | \"protectedRoutes\">\n): RouteMatch {\n // Check public routes first (if specified)\n if (config.publicRoutes && matchesAnyRoute(pathname, config.publicRoutes)) {\n return { type: \"public\" }\n }\n\n // Check protected routes\n const match = findMatchingProtectedRoute(pathname, config.protectedRoutes)\n if (match) {\n return { type: \"protected\", requiredRoles: match.requiredRoles }\n }\n\n // Not explicitly configured = unprotected\n return { type: \"unprotected\" }\n}\n\n/**\n * Create a default configuration for a micro-frontend\n */\nexport function createConfig(\n options: Partial<MicroFrontendConfig> & Pick<MicroFrontendConfig, \"basePath\">\n): MicroFrontendConfig {\n return {\n basePath: options.basePath,\n protectedRoutes: options.protectedRoutes || {\n \"/dashboard\": [],\n \"/admin\": [\"organization.owner\"],\n },\n publicRoutes: options.publicRoutes || [],\n }\n}\n\n/**\n * Build a sign-in redirect URL\n * Uses AUTH_URL environment variable internally.\n * \n * @param callbackUrl - Optional callback URL to return to after sign-in\n */\nexport function buildSignInUrl(callbackUrl?: string): URL {\n const authUrl = getAuthUrl()\n const url = new URL(\"/auth/signin\", authUrl)\n if (callbackUrl) {\n url.searchParams.set(\"callbackUrl\", callbackUrl)\n }\n return url\n}\n\n/**\n * Build a sign-out redirect URL\n * Uses AUTH_URL environment variable internally.\n * \n * @param callbackUrl - Optional callback URL to return to after sign-out\n */\nexport function buildSignOutUrl(callbackUrl?: string): URL {\n const authUrl = getAuthUrl()\n const url = new URL(\"/auth/signout\", authUrl)\n if (callbackUrl) {\n url.searchParams.set(\"callbackUrl\", callbackUrl)\n }\n return url\n}\n\n"]}
@@ -0,0 +1,195 @@
1
+ import { D as DecodeResult, S as SessionCookie, a as DecodedToken, b as Session, M as MicroFrontendConfig, R as RouteMatch, c as RouteConfig } from './types-YvOY9KNP.cjs';
2
+ export { d as SessionUser } from './types-YvOY9KNP.cjs';
3
+
4
+ /**
5
+ * Kernel Bridge JWT
6
+ * Framework-agnostic JWT decoding for AuthJS/NextAuth tokens
7
+ */
8
+
9
+ /**
10
+ * Cookie names used by AuthJS/NextAuth
11
+ * Defaults to authjs.session-token, can be overridden via AUTH_COOKIE env var
12
+ */
13
+ declare const COOKIE_NAMES: {
14
+ readonly secure: string;
15
+ readonly dev: string;
16
+ };
17
+ /**
18
+ * Get the appropriate salt for JWT decoding based on cookie type
19
+ */
20
+ declare function getSalt(isSecure: boolean): string;
21
+ /**
22
+ * Get the cookie name based on security mode
23
+ */
24
+ declare function getCookieName(isSecure: boolean): string;
25
+ /**
26
+ * Check if a token is expired
27
+ */
28
+ declare function isTokenExpired(decoded: DecodedToken): boolean;
29
+ /**
30
+ * Map decoded JWT payload to Session structure
31
+ */
32
+ declare function mapToSession(decoded: DecodedToken): Session;
33
+ /**
34
+ * Decode and validate a session token
35
+ *
36
+ * This is the core function - framework-agnostic JWT decoding.
37
+ * The caller is responsible for extracting the token from their framework's
38
+ * cookie/header mechanism.
39
+ *
40
+ * @param token - The JWT session token
41
+ * @param secret - The AUTH_SECRET used to sign the token
42
+ * @param isSecure - Whether the token came from a secure cookie
43
+ * @returns DecodeResult with session data or error
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const result = await decodeSessionToken(token, process.env.AUTH_SECRET, isSecure)
48
+ * if (result.success) {
49
+ * console.log(result.session.user.email)
50
+ * } else {
51
+ * console.error(result.error)
52
+ * }
53
+ * ```
54
+ */
55
+ declare function decodeSessionToken(token: string | undefined, secret: string | undefined, isSecure?: boolean): Promise<DecodeResult>;
56
+ /**
57
+ * Extract session cookie from a cookies object (generic interface)
58
+ *
59
+ * This works with any object that has a `get(name)` method returning
60
+ * `{ value: string } | undefined`, like Next.js cookies() or similar.
61
+ *
62
+ * @param cookies - Object with get(name) method
63
+ * @returns SessionCookie or undefined if no session cookie found
64
+ */
65
+ declare function extractSessionCookie(cookies: {
66
+ get(name: string): {
67
+ value: string;
68
+ } | undefined;
69
+ }): SessionCookie | undefined;
70
+
71
+ /**
72
+ * Kernel Bridge Roles
73
+ * Role checking and permission utilities
74
+ */
75
+ /**
76
+ * Options for fetching user roles from the kernel
77
+ */
78
+ interface FetchRolesOptions {
79
+ /**
80
+ * Organization ID to fetch roles in
81
+ */
82
+ organizationId: string;
83
+ /**
84
+ * Session token for authentication (user ID is determined from the token)
85
+ */
86
+ sessionToken: string;
87
+ /**
88
+ * Whether using secure cookie
89
+ * Defaults to NODE_ENV === "production" if not provided
90
+ */
91
+ isSecure?: boolean;
92
+ /**
93
+ * Custom fetch function (optional, for testing or SSR)
94
+ */
95
+ fetchFn?: typeof fetch;
96
+ }
97
+ /**
98
+ * Result of role fetching operation
99
+ */
100
+ type FetchRolesResult = {
101
+ success: true;
102
+ roles: string[];
103
+ } | {
104
+ success: false;
105
+ error: string;
106
+ };
107
+ /**
108
+ * Fetch user roles from the kernel API
109
+ *
110
+ * This is a framework-agnostic function that makes a fetch request
111
+ * to the kernel's roles endpoint. Uses AUTH_URL environment variable internally.
112
+ * The user ID is determined from the session token.
113
+ *
114
+ * @param options - Configuration for fetching roles
115
+ * @returns Promise with roles array or error
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const result = await fetchUserRoles({
120
+ * organizationId: "org-123",
121
+ * sessionToken: token,
122
+ * // isSecure defaults to NODE_ENV === "production"
123
+ * })
124
+ * if (result.success) {
125
+ * console.log(result.roles)
126
+ * }
127
+ * ```
128
+ */
129
+ declare function fetchUserRoles(options: FetchRolesOptions): Promise<FetchRolesResult>;
130
+ /**
131
+ * Check if user has at least one of the required roles
132
+ */
133
+ declare function hasAnyRole(userRoles: string[], requiredRoles: string[]): boolean;
134
+ /**
135
+ * Check if user has all of the required roles
136
+ */
137
+ declare function hasAllRoles(userRoles: string[], requiredRoles: string[]): boolean;
138
+ /**
139
+ * Check if user has a specific role
140
+ */
141
+ declare function hasRole(userRoles: string[], role: string): boolean;
142
+
143
+ /**
144
+ * Kernel Bridge Routes
145
+ * Route matching and protection utilities
146
+ */
147
+
148
+ /**
149
+ * Check if a pathname matches any route in the list
150
+ */
151
+ declare function matchesAnyRoute(pathname: string, routes: string[]): boolean;
152
+ /**
153
+ * Find the first matching protected route for a pathname
154
+ */
155
+ declare function findMatchingProtectedRoute(pathname: string, protectedRoutes: RouteConfig): {
156
+ route: string;
157
+ requiredRoles: string[];
158
+ } | undefined;
159
+ /**
160
+ * Match a pathname against route configuration
161
+ *
162
+ * @param pathname - The URL pathname to match
163
+ * @param config - Micro-frontend configuration
164
+ * @returns RouteMatch indicating the type of route
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * const match = matchRoute("/dashboard", {
169
+ * publicRoutes: ["/", "/api/health"],
170
+ * protectedRoutes: { "/dashboard": [], "/admin": ["organization.owner"] },
171
+ * })
172
+ * // Returns: { type: "protected", requiredRoles: [] }
173
+ * ```
174
+ */
175
+ declare function matchRoute(pathname: string, config: Pick<MicroFrontendConfig, "publicRoutes" | "protectedRoutes">): RouteMatch;
176
+ /**
177
+ * Create a default configuration for a micro-frontend
178
+ */
179
+ declare function createConfig(options: Partial<MicroFrontendConfig> & Pick<MicroFrontendConfig, "basePath">): MicroFrontendConfig;
180
+ /**
181
+ * Build a sign-in redirect URL
182
+ * Uses AUTH_URL environment variable internally.
183
+ *
184
+ * @param callbackUrl - Optional callback URL to return to after sign-in
185
+ */
186
+ declare function buildSignInUrl(callbackUrl?: string): URL;
187
+ /**
188
+ * Build a sign-out redirect URL
189
+ * Uses AUTH_URL environment variable internally.
190
+ *
191
+ * @param callbackUrl - Optional callback URL to return to after sign-out
192
+ */
193
+ declare function buildSignOutUrl(callbackUrl?: string): URL;
194
+
195
+ export { COOKIE_NAMES, DecodeResult, DecodedToken, type FetchRolesOptions, type FetchRolesResult, MicroFrontendConfig, RouteConfig, RouteMatch, Session, SessionCookie, buildSignInUrl, buildSignOutUrl, createConfig, decodeSessionToken, extractSessionCookie, fetchUserRoles, findMatchingProtectedRoute, getCookieName, getSalt, hasAllRoles, hasAnyRole, hasRole, isTokenExpired, mapToSession, matchRoute, matchesAnyRoute };