@kyro-cms/core 0.9.5 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/api-handler-graphql.cjs +10 -10
  2. package/dist/api-handler-graphql.js +6 -6
  3. package/dist/api-handler-trpc.cjs +8 -8
  4. package/dist/api-handler-trpc.js +6 -6
  5. package/dist/api-handler.cjs +9 -9
  6. package/dist/api-handler.js +6 -6
  7. package/dist/{chunk-YFAVQQTU.js → chunk-AX2TZRQJ.js} +3 -3
  8. package/dist/{chunk-YFAVQQTU.js.map → chunk-AX2TZRQJ.js.map} +1 -1
  9. package/dist/{chunk-5H3MWQJS.js → chunk-CMXVTUYV.js} +12 -12
  10. package/dist/chunk-CMXVTUYV.js.map +1 -0
  11. package/dist/{chunk-E2763JUP.cjs → chunk-DRVOUQMT.cjs} +27 -27
  12. package/dist/chunk-DRVOUQMT.cjs.map +1 -0
  13. package/dist/{chunk-4M7X5HAB.cjs → chunk-FKKQUMXR.cjs} +109 -3
  14. package/dist/chunk-FKKQUMXR.cjs.map +1 -0
  15. package/dist/{chunk-PV2I2KMI.cjs → chunk-HVCUIII2.cjs} +21 -75
  16. package/dist/chunk-HVCUIII2.cjs.map +1 -0
  17. package/dist/{chunk-CJONKRHJ.js → chunk-NZEUU7QB.js} +108 -3
  18. package/dist/chunk-NZEUU7QB.js.map +1 -0
  19. package/dist/{chunk-NWUEVLQT.cjs → chunk-OZ3CCTTA.cjs} +5 -5
  20. package/dist/{chunk-NWUEVLQT.cjs.map → chunk-OZ3CCTTA.cjs.map} +1 -1
  21. package/dist/chunk-PONTBXR5.js +842 -0
  22. package/dist/chunk-PONTBXR5.js.map +1 -0
  23. package/dist/{chunk-CNKT4PME.cjs → chunk-QVJNSAQL.cjs} +71 -149
  24. package/dist/chunk-QVJNSAQL.cjs.map +1 -0
  25. package/dist/{chunk-OHC6UHFY.js → chunk-QX3WNQ7V.js} +18 -72
  26. package/dist/chunk-QX3WNQ7V.js.map +1 -0
  27. package/dist/chunk-RRKCIAPU.cjs +848 -0
  28. package/dist/chunk-RRKCIAPU.cjs.map +1 -0
  29. package/dist/{chunk-IPTZM3VE.js → chunk-VLK5SJRI.js} +56 -134
  30. package/dist/chunk-VLK5SJRI.js.map +1 -0
  31. package/dist/graphql/index.cjs +8 -4
  32. package/dist/graphql/index.d.cts +4 -1
  33. package/dist/graphql/index.d.ts +4 -1
  34. package/dist/graphql/index.js +2 -2
  35. package/dist/index.cjs +57 -57
  36. package/dist/index.js +6 -6
  37. package/dist/rest/index.cjs +4 -4
  38. package/dist/rest/index.js +2 -2
  39. package/dist/trpc/index.cjs +11 -11
  40. package/dist/trpc/index.js +2 -2
  41. package/package.json +2 -2
  42. package/dist/chunk-3HR772HI.cjs +0 -555
  43. package/dist/chunk-3HR772HI.cjs.map +0 -1
  44. package/dist/chunk-4M7X5HAB.cjs.map +0 -1
  45. package/dist/chunk-5H3MWQJS.js.map +0 -1
  46. package/dist/chunk-CJONKRHJ.js.map +0 -1
  47. package/dist/chunk-CNKT4PME.cjs.map +0 -1
  48. package/dist/chunk-E2763JUP.cjs.map +0 -1
  49. package/dist/chunk-IPTZM3VE.js.map +0 -1
  50. package/dist/chunk-L5UKKZQN.js +0 -552
  51. package/dist/chunk-L5UKKZQN.js.map +0 -1
  52. package/dist/chunk-OHC6UHFY.js.map +0 -1
  53. package/dist/chunk-PV2I2KMI.cjs.map +0 -1
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var chunkNKPKR5BW_cjs = require('./chunk-NKPKR5BW.cjs');
3
4
  var crypto = require('crypto');
4
5
 
5
6
  // src/access/types.ts
@@ -159,15 +160,120 @@ function generateApiKeyPrefix(key) {
159
160
  return key.substring(0, 8);
160
161
  }
161
162
 
163
+ // src/access/checker.ts
164
+ function actionToPermission(operation) {
165
+ if (operation === "read") return "read";
166
+ if (operation === "create") return "create";
167
+ if (operation === "update") return "update";
168
+ return "delete";
169
+ }
170
+ function isDefaultAllowed(operation, defaultAccess) {
171
+ const levels = {
172
+ none: false,
173
+ read: operation === "read",
174
+ create: operation === "read" || operation === "create",
175
+ update: operation === "read" || operation === "create" || operation === "update",
176
+ delete: operation === "read" || operation === "create" || operation === "update" || operation === "delete",
177
+ admin: true
178
+ };
179
+ return levels[defaultAccess] || false;
180
+ }
181
+ async function checkCollectionAccess(config, operation, context, options = {}) {
182
+ const { user, req, tenantID, apiKey } = context;
183
+ const { enablePublicAccess = true, defaultAccess = "none" } = options;
184
+ const accessRule = config.access?.[operation];
185
+ if (accessRule) {
186
+ const allowed = await evaluateAccess(accessRule, {
187
+ req,
188
+ user,
189
+ tenantID
190
+ });
191
+ if (allowed === false) {
192
+ return { allowed: false, error: "Access denied", status: 403 };
193
+ }
194
+ if (typeof allowed === "object") {
195
+ return { allowed: true, extraWhere: allowed };
196
+ }
197
+ return { allowed: true };
198
+ }
199
+ if (apiKey?.permissions?.length > 0) {
200
+ const resource = config.slug;
201
+ const action = actionToPermission(operation);
202
+ const permission = `${resource}:${action}`;
203
+ if (!hasApiKeyPermission(apiKey.permissions, permission) && !hasApiKeyPermission(apiKey.permissions, `${resource}:admin`)) {
204
+ return { allowed: false, error: "Access denied: insufficient permissions", status: 403 };
205
+ }
206
+ return { allowed: true };
207
+ }
208
+ if (user) {
209
+ const resource = config.slug;
210
+ const action = actionToPermission(operation);
211
+ const permission = `${resource}:${action}`;
212
+ const userHas = chunkNKPKR5BW_cjs.hasPermission(
213
+ { id: user.id, email: user.email, role: user.role },
214
+ permission
215
+ );
216
+ const adminHas = chunkNKPKR5BW_cjs.hasPermission(
217
+ { id: user.id, email: user.email, role: user.role },
218
+ `${resource}:admin`
219
+ );
220
+ if (userHas || adminHas) {
221
+ return { allowed: true };
222
+ }
223
+ return { allowed: false, error: "Access denied: missing RBAC permission", status: 403 };
224
+ }
225
+ const defaultAllowed = isDefaultAllowed(operation, defaultAccess);
226
+ if (enablePublicAccess && defaultAllowed) {
227
+ return { allowed: true };
228
+ }
229
+ return { allowed: false, error: "Authentication required", status: 401 };
230
+ }
231
+ async function checkGlobalAccess(config, operation, context, options = {}) {
232
+ const { user, req, tenantID } = context;
233
+ const { enablePublicAccess = true } = options;
234
+ const accessRule = config.access?.[operation];
235
+ if (accessRule) {
236
+ const allowed = await evaluateAccess(accessRule, {
237
+ req,
238
+ user,
239
+ tenantID
240
+ });
241
+ if (allowed === false) {
242
+ return { allowed: false, error: "Access denied", status: 403 };
243
+ }
244
+ return { allowed: true };
245
+ }
246
+ if (user) {
247
+ const permission = `globals:${operation}`;
248
+ const userHas = chunkNKPKR5BW_cjs.hasPermission(
249
+ { id: user.id, email: user.email, role: user.role },
250
+ permission
251
+ );
252
+ const adminHas = chunkNKPKR5BW_cjs.hasPermission(
253
+ { id: user.id, email: user.email, role: user.role },
254
+ "globals:admin"
255
+ );
256
+ if (userHas || adminHas) {
257
+ return { allowed: true };
258
+ }
259
+ return { allowed: false, error: "Access denied: missing RBAC permission", status: 403 };
260
+ }
261
+ if (enablePublicAccess) {
262
+ return { allowed: true };
263
+ }
264
+ return { allowed: false, error: "Authentication required", status: 401 };
265
+ }
266
+
162
267
  exports.API_KEY_COLLECTION = API_KEY_COLLECTION;
268
+ exports.checkCollectionAccess = checkCollectionAccess;
269
+ exports.checkGlobalAccess = checkGlobalAccess;
163
270
  exports.createApiKeyContext = createApiKeyContext;
164
271
  exports.evaluateAccess = evaluateAccess;
165
272
  exports.extractApiKeyFromRequest = extractApiKeyFromRequest;
166
273
  exports.generateApiKey = generateApiKey;
167
274
  exports.generateApiKeyPrefix = generateApiKeyPrefix;
168
275
  exports.getWhereClause = getWhereClause;
169
- exports.hasApiKeyPermission = hasApiKeyPermission;
170
276
  exports.mergeWhereClauses = mergeWhereClauses;
171
277
  exports.validateApiKey = validateApiKey;
172
- //# sourceMappingURL=chunk-4M7X5HAB.cjs.map
173
- //# sourceMappingURL=chunk-4M7X5HAB.cjs.map
278
+ //# sourceMappingURL=chunk-FKKQUMXR.cjs.map
279
+ //# sourceMappingURL=chunk-FKKQUMXR.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/access/types.ts","../src/auth/api-key.ts","../src/access/checker.ts"],"names":["timingSafeEqual","hasPermission"],"mappings":"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","file":"chunk-FKKQUMXR.cjs","sourcesContent":["import type { User, Request } from '../hooks/types.js';\n\n// ============================================================================\n// Access Control Types\n// ============================================================================\n\nexport interface WhereClause {\n [field: string]: any;\n}\n\nexport interface AccessArgs {\n req: Request;\n user?: User;\n data?: any;\n doc?: any;\n id?: string;\n tenantID?: string;\n context?: Record<string, any>;\n}\n\nexport type AccessControl = boolean | ((args: AccessArgs) => Promise<boolean | WhereClause> | boolean | WhereClause);\n\nexport interface CollectionAccess {\n create?: AccessControl;\n read?: AccessControl;\n update?: AccessControl;\n delete?: AccessControl;\n admin?: AccessControl;\n unlock?: AccessControl;\n readVersions?: AccessControl;\n}\n\nexport interface GlobalAccess {\n read?: AccessControl;\n update?: AccessControl;\n}\n\nexport interface FieldAccess {\n create?: AccessControl;\n read?: AccessControl;\n update?: AccessControl;\n}\n\n// ============================================================================\n// Access Control Evaluation\n// ============================================================================\n\nexport async function evaluateAccess(\n access: AccessControl,\n args: AccessArgs\n): Promise<boolean | WhereClause> {\n if (typeof access === 'boolean') {\n return access;\n }\n if (typeof access === 'function') {\n return await access(args);\n }\n return true;\n}\n\nexport function mergeWhereClauses(\n ...whereClauses: (WhereClause | boolean | undefined)[]\n): WhereClause {\n const result: WhereClause = {};\n for (const clause of whereClauses) {\n if (clause && typeof clause === 'object') {\n Object.assign(result, clause);\n }\n }\n return result;\n}\n\nexport function getWhereClause(\n access: AccessControl,\n args: AccessArgs\n): Promise<WhereClause | undefined> {\n return evaluateAccess(access, args).then(result => {\n if (result === true) return undefined;\n if (result === false) return { _id: { $eq: null } };\n return result;\n });\n}\n","import { timingSafeEqual } from \"crypto\";\nimport type { BaseAdapter } from \"../registry/types.js\";\nimport type { AuthUser, UserRole } from \"./types.js\";\n\nexport interface ApiKeyRecord {\n id: string;\n userId: string;\n name: string;\n key: string;\n keyPrefix: string;\n permissions: string[];\n lastUsedAt?: string;\n expiresAt?: string;\n createdAt: string;\n}\n\nexport interface ApiKeyValidationResult {\n valid: boolean;\n userId?: string;\n user?: Partial<AuthUser>;\n permissions?: string[];\n apiKeyId?: string;\n error?: string;\n tenantId?: string;\n role?: UserRole;\n}\n\nexport interface ApiKeyContext {\n userId: string;\n user: Partial<AuthUser>;\n permissions: string[];\n apiKeyId: string;\n tenantId?: string;\n role?: UserRole;\n}\n\nexport const API_KEY_COLLECTION = \"_api_keys\";\n\nfunction generateKeyPrefix(key: string): string {\n return key.substring(0, 8);\n}\n\nfunction constantTimeCompare(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n try {\n return timingSafeEqual(Buffer.from(a), Buffer.from(b));\n } catch {\n return false;\n }\n}\n\nexport async function validateApiKey(\n rawKey: string,\n db: BaseAdapter,\n userLookup?: (userId: string) => Promise<Partial<AuthUser> | null>,\n): Promise<ApiKeyValidationResult> {\n if (!rawKey || typeof rawKey !== \"string\") {\n return { valid: false, error: \"No API key provided\" };\n }\n\n if (!rawKey.startsWith(\"kyro_\")) {\n return { valid: false, error: \"Invalid API key format\" };\n }\n\n const keyPrefix = generateKeyPrefix(rawKey);\n\n try {\n const result = await db.find({\n collection: API_KEY_COLLECTION,\n where: { keyPrefix: { equals: keyPrefix } },\n limit: 100,\n page: 1,\n });\n\n if (!result.docs || result.docs.length === 0) {\n return { valid: false, error: \"Invalid API key\" };\n }\n\n let matchedKey: ApiKeyRecord | null = null;\n for (const doc of result.docs) {\n const record = doc as unknown as ApiKeyRecord;\n if (constantTimeCompare(record.key, rawKey)) {\n matchedKey = record;\n break;\n }\n }\n\n if (!matchedKey) {\n return { valid: false, error: \"Invalid API key\" };\n }\n\n if (matchedKey.expiresAt) {\n const expiresAt = new Date(matchedKey.expiresAt);\n if (expiresAt < new Date()) {\n return { valid: false, error: \"API key has expired\" };\n }\n }\n\n try {\n await db.update({\n collection: API_KEY_COLLECTION,\n id: matchedKey.id,\n data: { lastUsedAt: new Date().toISOString() },\n });\n } catch {\n // Non-critical: don't fail if lastUsedAt update fails\n }\n\n const user: Partial<AuthUser> = {\n id: matchedKey.userId,\n role: (matchedKey as any).role || \"author\",\n tenantId: (matchedKey as any).tenantId,\n };\n\n if (userLookup) {\n const dbUser = await userLookup(matchedKey.userId);\n if (dbUser) {\n Object.assign(user, dbUser);\n }\n }\n\n return {\n valid: true,\n userId: matchedKey.userId,\n user,\n permissions: matchedKey.permissions || [],\n apiKeyId: matchedKey.id,\n tenantId: user.tenantId,\n role: user.role,\n };\n } catch (error) {\n console.error(\"[ApiKey] Validation error:\", error);\n return { valid: false, error: \"Failed to validate API key\" };\n }\n}\n\nexport function extractApiKeyFromRequest(request: Request): string | null {\n const authHeader = request.headers.get(\"Authorization\");\n if (authHeader) {\n if (authHeader.startsWith(\"ApiKey \")) {\n return authHeader.slice(7).trim();\n }\n if (authHeader.startsWith(\"Bearer \")) {\n return null;\n }\n }\n\n const xApiKey = request.headers.get(\"X-API-Key\");\n if (xApiKey) {\n return xApiKey.trim();\n }\n\n return null;\n}\n\nexport function createApiKeyContext(\n result: ApiKeyValidationResult,\n): ApiKeyContext | null {\n if (!result.valid || !result.userId) {\n return null;\n }\n return {\n userId: result.userId,\n user: result.user || {},\n permissions: result.permissions || [],\n apiKeyId: result.apiKeyId || \"\",\n tenantId: result.tenantId,\n role: result.role,\n };\n}\n\nexport function hasApiKeyPermission(\n permissions: string[],\n required: string,\n): boolean {\n if (permissions.length === 0) return false;\n if (permissions.includes(\"*\")) return true;\n if (permissions.includes(required)) return true;\n\n const [resource, action] = required.split(\":\");\n if (permissions.includes(`${resource}:*`)) return true;\n\n return false;\n}\n\nexport function generateApiKey(): string {\n const chars = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n let suffix = \"\";\n for (let i = 0; i < 32; i++) {\n suffix += chars[Math.floor(Math.random() * chars.length)];\n }\n return `kyro_${suffix}`;\n}\n\nexport function generateApiKeyPrefix(key: string): string {\n return key.substring(0, 8);\n}\n","import type { User, Request } from '../hooks/types.js';\nimport { evaluateAccess, type WhereClause } from './types.js';\nimport { hasPermission } from '../auth/rbac/checker.js';\nimport { hasApiKeyPermission } from '../auth/api-key.js';\n\nexport interface AccessCheckResult {\n allowed: boolean;\n extraWhere?: WhereClause;\n error?: string;\n status?: number;\n}\n\nexport interface AccessContext {\n user?: User;\n req?: Request;\n tenantID?: string;\n apiKey?: any;\n}\n\nexport interface AccessOptions {\n enablePublicAccess?: boolean;\n defaultAccess?: string;\n}\n\nfunction actionToPermission(\n operation: \"read\" | \"create\" | \"update\" | \"delete\",\n): string {\n if (operation === \"read\") return \"read\";\n if (operation === \"create\") return \"create\";\n if (operation === \"update\") return \"update\";\n return \"delete\";\n}\n\nfunction isDefaultAllowed(\n operation: \"read\" | \"create\" | \"update\" | \"delete\",\n defaultAccess: string,\n): boolean {\n const levels: Record<string, boolean> = {\n none: false,\n read: operation === \"read\",\n create: operation === \"read\" || operation === \"create\",\n update: operation === \"read\" || operation === \"create\" || operation === \"update\",\n delete: operation === \"read\" || operation === \"create\" || operation === \"update\" || operation === \"delete\",\n admin: true,\n };\n return levels[defaultAccess] || false;\n}\n\nexport async function checkCollectionAccess(\n config: { access?: any; slug: string },\n operation: \"read\" | \"create\" | \"update\" | \"delete\",\n context: AccessContext,\n options: AccessOptions = {},\n): Promise<AccessCheckResult> {\n const { user, req, tenantID, apiKey } = context;\n const { enablePublicAccess = true, defaultAccess = \"none\" } = options;\n const accessRule = config.access?.[operation];\n\n // Custom access function (highest priority)\n if (accessRule) {\n const allowed = await evaluateAccess(accessRule, {\n req: req!,\n user,\n tenantID,\n });\n if (allowed === false) {\n return { allowed: false, error: \"Access denied\", status: 403 };\n }\n if (typeof allowed === \"object\") {\n return { allowed: true, extraWhere: allowed as WhereClause };\n }\n return { allowed: true };\n }\n\n // API key permission check\n if (apiKey?.permissions?.length > 0) {\n const resource = config.slug;\n const action = actionToPermission(operation);\n const permission = `${resource}:${action}`;\n if (\n !hasApiKeyPermission(apiKey.permissions, permission) &&\n !hasApiKeyPermission(apiKey.permissions, `${resource}:admin`)\n ) {\n return { allowed: false, error: \"Access denied: insufficient permissions\", status: 403 };\n }\n return { allowed: true };\n }\n\n // No accessRule, no apiKey — authenticated user RBAC\n if (user) {\n const resource = config.slug;\n const action = actionToPermission(operation);\n const permission = `${resource}:${action}`;\n\n const userHas = hasPermission(\n { id: user.id, email: user.email, role: user.role } as any,\n permission,\n );\n const adminHas = hasPermission(\n { id: user.id, email: user.email, role: user.role } as any,\n `${resource}:admin`,\n );\n\n if (userHas || adminHas) {\n return { allowed: true };\n }\n return { allowed: false, error: \"Access denied: missing RBAC permission\", status: 403 };\n }\n\n // Unauthenticated — check public access\n const defaultAllowed = isDefaultAllowed(operation, defaultAccess);\n if (enablePublicAccess && defaultAllowed) {\n return { allowed: true };\n }\n\n return { allowed: false, error: \"Authentication required\", status: 401 };\n}\n\nexport async function checkGlobalAccess(\n config: { access?: any; slug: string },\n operation: \"read\" | \"update\",\n context: AccessContext,\n options: AccessOptions = {},\n): Promise<AccessCheckResult> {\n const { user, req, tenantID } = context;\n const { enablePublicAccess = true } = options;\n const accessRule = config.access?.[operation];\n\n // Custom access function\n if (accessRule) {\n const allowed = await evaluateAccess(accessRule, {\n req: req!,\n user,\n tenantID,\n });\n if (allowed === false) {\n return { allowed: false, error: \"Access denied\", status: 403 };\n }\n return { allowed: true };\n }\n\n // Authenticated user RBAC\n if (user) {\n const permission = `globals:${operation}`;\n const userHas = hasPermission(\n { id: user.id, email: user.email, role: user.role } as any,\n permission,\n );\n const adminHas = hasPermission(\n { id: user.id, email: user.email, role: user.role } as any,\n \"globals:admin\",\n );\n if (userHas || adminHas) {\n return { allowed: true };\n }\n return { allowed: false, error: \"Access denied: missing RBAC permission\", status: 403 };\n }\n\n // Unauthenticated\n if (enablePublicAccess) {\n return { allowed: true };\n }\n\n return { allowed: false, error: \"Authentication required\", status: 401 };\n}\n"]}
@@ -1,8 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkQFLB4EIJ_cjs = require('./chunk-QFLB4EIJ.cjs');
4
- var chunk4M7X5HAB_cjs = require('./chunk-4M7X5HAB.cjs');
5
- var chunkNKPKR5BW_cjs = require('./chunk-NKPKR5BW.cjs');
4
+ var chunkFKKQUMXR_cjs = require('./chunk-FKKQUMXR.cjs');
6
5
 
7
6
  // src/api/trpc/context.ts
8
7
  async function createContext(options) {
@@ -16,9 +15,9 @@ async function createContext(options) {
16
15
  webhookService,
17
16
  settings: options.settings
18
17
  };
19
- const apiKeyRaw = chunk4M7X5HAB_cjs.extractApiKeyFromRequest(options.req);
18
+ const apiKeyRaw = chunkFKKQUMXR_cjs.extractApiKeyFromRequest(options.req);
20
19
  if (apiKeyRaw) {
21
- const result = await chunk4M7X5HAB_cjs.validateApiKey(apiKeyRaw, options.db, async (userId) => {
20
+ const result = await chunkFKKQUMXR_cjs.validateApiKey(apiKeyRaw, options.db, async (userId) => {
22
21
  try {
23
22
  const user = await options.db.findByID({ collection: "users", id: userId });
24
23
  return user || null;
@@ -29,7 +28,7 @@ async function createContext(options) {
29
28
  if (result.valid) {
30
29
  baseContext.user = result.user || options.user;
31
30
  baseContext.tenantID = result.tenantId || options.tenantID;
32
- baseContext.apiKey = chunk4M7X5HAB_cjs.createApiKeyContext(result);
31
+ baseContext.apiKey = chunkFKKQUMXR_cjs.createApiKeyContext(result);
33
32
  }
34
33
  }
35
34
  return baseContext;
@@ -96,42 +95,14 @@ function normalizeEmptyStrings(data, fields) {
96
95
  }
97
96
  }
98
97
  async function checkTRPCAccess(config, operation, ctx) {
99
- const accessRule = config.access?.[operation];
100
- const apiKey = ctx.apiKey;
101
- if (apiKey && apiKey.permissions && apiKey.permissions.length > 0) {
102
- const resource = config.slug;
103
- const action = operation === "read" ? "read" : operation === "create" ? "create" : "update";
104
- const permission = `${resource}:${action}`;
105
- if (!chunk4M7X5HAB_cjs.hasApiKeyPermission(apiKey.permissions, permission) && !chunk4M7X5HAB_cjs.hasApiKeyPermission(apiKey.permissions, `${resource}:admin`)) {
106
- throw new Error(`Access denied: missing API key permission ${permission}`);
107
- }
108
- }
109
- if (ctx.user && !(apiKey && apiKey.permissions && apiKey.permissions.length > 0)) {
110
- const resource = config.slug;
111
- const action = operation === "read" ? "read" : operation === "create" ? "create" : operation === "update" ? "update" : "delete";
112
- const permission = `${resource}:${action}`;
113
- const userHasPermission = chunkNKPKR5BW_cjs.hasPermission(
114
- { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role },
115
- permission
116
- );
117
- if (!userHasPermission && !chunkNKPKR5BW_cjs.hasPermission(
118
- { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role },
119
- `${resource}:admin`
120
- )) {
121
- if (!accessRule) {
122
- throw new Error(`Access denied: missing RBAC permission ${permission}`);
123
- }
124
- }
125
- }
126
- if (accessRule) {
127
- const allowed = await chunk4M7X5HAB_cjs.evaluateAccess(accessRule, {
128
- req: ctx.req,
129
- user: ctx.user,
130
- tenantID: ctx.tenantID
131
- });
132
- if (allowed === false) throw new Error("Access denied");
133
- } else if (!ctx.user && !ctx.apiKey) {
134
- throw new Error("Access denied: authentication required");
98
+ const result = await chunkFKKQUMXR_cjs.checkCollectionAccess(config, operation, {
99
+ user: ctx.user,
100
+ req: ctx.req,
101
+ tenantID: ctx.tenantID,
102
+ apiKey: ctx.apiKey
103
+ });
104
+ if (!result.allowed) {
105
+ throw new Error(result.error || "Access denied");
135
106
  }
136
107
  if (ctx.tenantID) {
137
108
  ctx.db.setTenantContext({ tenantId: ctx.tenantID, userId: ctx.user?.id ?? "", role: ctx.user?.role, isSuperAdmin: ctx.user?.role === "super_admin" });
@@ -465,38 +436,13 @@ function createCountProcedure(ctx) {
465
436
 
466
437
  // src/api/trpc/router.ts
467
438
  async function checkGlobalAccessTRPC(global, operation, ctx) {
468
- const accessRule = global.access?.[operation];
469
- const apiKey = ctx.apiKey;
470
- if (apiKey && apiKey.permissions && apiKey.permissions.length > 0) {
471
- const permission = `globals:${operation}`;
472
- if (!chunk4M7X5HAB_cjs.hasApiKeyPermission(apiKey.permissions, permission) && !chunk4M7X5HAB_cjs.hasApiKeyPermission(apiKey.permissions, "globals:admin")) {
473
- throw new Error(`Access denied: missing API key permission ${permission}`);
474
- }
475
- }
476
- if (ctx.user) {
477
- const permission = `globals:${operation}`;
478
- const userHasPermission = chunkNKPKR5BW_cjs.hasPermission(
479
- { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role },
480
- permission
481
- );
482
- if (!userHasPermission && !chunkNKPKR5BW_cjs.hasPermission(
483
- { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role },
484
- "globals:admin"
485
- )) {
486
- if (!accessRule) {
487
- throw new Error(`Access denied: missing RBAC permission ${permission}`);
488
- }
489
- }
490
- }
491
- if (accessRule) {
492
- const allowed = await chunk4M7X5HAB_cjs.evaluateAccess(accessRule, {
493
- req: ctx.req,
494
- user: ctx.user,
495
- tenantID: ctx.tenantID
496
- });
497
- if (allowed === false) throw new Error("Access denied");
498
- } else if (!ctx.user && !ctx.apiKey) {
499
- throw new Error("Access denied: authentication required");
439
+ const result = await chunkFKKQUMXR_cjs.checkGlobalAccess(global, operation, {
440
+ user: ctx.user,
441
+ req: ctx.req,
442
+ tenantID: ctx.tenantID
443
+ });
444
+ if (!result.allowed) {
445
+ throw new Error(result.error || "Access denied");
500
446
  }
501
447
  if (ctx.tenantID) {
502
448
  ctx.db.setTenantContext({ tenantId: ctx.tenantID, userId: ctx.user?.id ?? "", role: ctx.user?.role, isSuperAdmin: ctx.user?.role === "super_admin" });
@@ -576,5 +522,5 @@ exports.createFindByIDProcedure = createFindByIDProcedure;
576
522
  exports.createFindProcedure = createFindProcedure;
577
523
  exports.createKyroServer = createKyroServer;
578
524
  exports.createUpdateProcedure = createUpdateProcedure;
579
- //# sourceMappingURL=chunk-PV2I2KMI.cjs.map
580
- //# sourceMappingURL=chunk-PV2I2KMI.cjs.map
525
+ //# sourceMappingURL=chunk-HVCUIII2.cjs.map
526
+ //# sourceMappingURL=chunk-HVCUIII2.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/trpc/context.ts","../src/api/trpc/procedures.ts","../src/api/trpc/router.ts"],"names":["createWebhookService","extractApiKeyFromRequest","validateApiKey","createApiKeyContext","WEBHOOK_EVENTS","checkCollectionAccess","checkGlobalAccess"],"mappings":";;;;;;AAsCA,eAAsB,cAAc,OAAA,EAOX;AACvB,EAAA,MAAM,cAAA,GAAiBA,sCAAA,CAAqB,OAAA,CAAQ,EAAE,CAAA;AAEtD,EAAA,MAAM,WAAA,GAA2B;AAAA,IAC/B,IAAI,OAAA,CAAQ,EAAA;AAAA,IACZ,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,KAAK,OAAA,CAAQ,GAAA;AAAA,IACb,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,cAAA;AAAA,IACA,UAAU,OAAA,CAAQ;AAAA,GACpB;AAEA,EAAA,MAAM,SAAA,GAAYC,0CAAA,CAAyB,OAAA,CAAQ,GAAU,CAAA;AAC7D,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,MAAM,SAAS,MAAMC,gCAAA,CAAe,WAAW,OAAA,CAAQ,EAAA,EAAI,OAAO,MAAA,KAAW;AAC3E,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,EAAA,CAAG,QAAA,CAAS,EAAE,UAAA,EAAY,OAAA,EAAS,EAAA,EAAI,MAAA,EAAQ,CAAA;AAC1E,QAAA,OAAO,IAAA,IAAQ,IAAA;AAAA,MACjB,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF,CAAC,CAAA;AACD,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,WAAA,CAAY,IAAA,GAAQ,MAAA,CAAO,IAAA,IAAiB,OAAA,CAAQ,IAAA;AACpD,MAAA,WAAA,CAAY,QAAA,GAAW,MAAA,CAAO,QAAA,IAAY,OAAA,CAAQ,QAAA;AAClD,MAAA,WAAA,CAAY,MAAA,GAASC,sCAAoB,MAAM,CAAA;AAAA,IACjD;AAAA,EACF;AAEA,EAAA,OAAO,WAAA;AACT;;;AChEA,IAAM,oBAAA,GAGF;AAAA,EACF,MAAA,EAAQ;AAAA,IACN,QAAQC,gCAAA,CAAe,YAAA;AAAA,IACvB,QAAQA,gCAAA,CAAe,YAAA;AAAA,IACvB,QAAQA,gCAAA,CAAe;AAAA;AAE3B,CAAA;AAEA,SAAS,eAAA,CACP,YACA,SAAA,EACc;AACd,EAAA,MAAM,MAAA,GAAS,qBAAqB,UAAU,CAAA;AAC9C,EAAA,IAAI,MAAA,EAAQ,OAAO,MAAA,CAAO,SAAS,CAAA;AACnC,EAAA,OAAO,cAAc,SAAS,CAAA,CAAA;AAChC;AAEA,eAAe,cAAA,CACb,GAAA,EACA,KAAA,EACA,OAAA,EAMA;AACA,EAAA,IAAI,CAAC,IAAI,cAAA,EAAgB;AACzB,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,CAAI,cAAA,CAAe,OAAA,CAAQ,KAAA,EAAO;AAAA,MACtC,YAAY,OAAA,CAAQ,UAAA;AAAA,MACpB,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,MAAM,OAAA,CAAQ,IAAA;AAAA,MACd,cAAc,OAAA,CAAQ,YAAA;AAAA,MACtB,MAAM,GAAA,CAAI,IAAA,GACN,EAAE,EAAA,EAAI,IAAI,IAAA,CAAK,EAAA,EAAI,KAAA,EAAO,GAAA,CAAI,KAAK,KAAA,EAAO,IAAA,EAAM,GAAA,CAAI,IAAA,CAAK,MAAK,GAC9D,KAAA,CAAA;AAAA,MACJ,UAAU,GAAA,CAAI;AAAA,KACf,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,4BAAA,EAA+B,KAAK,CAAA,CAAA,CAAA,EAAK,GAAG,CAAA;AAAA,EAC5D;AACF;AAMA,SAAS,qBAAA,CAAsB,MAAW,MAAA,EAAuB;AAC/D,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACvC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,IAAI,CAAC,KAAA,CAAM,IAAA,IAAQ,EAAE,KAAA,CAAM,QAAQ,IAAA,CAAA,EAAO;AAC1C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,IAAI,QAAQ,EAAA,EAAI;AACd,MAAA,MAAM,SAAA,GAAY,MAAM,IAAA,KAAS,MAAA,IAAU,MAAM,IAAA,KAAS,UAAA,IAAc,MAAM,IAAA,KAAS,MAAA,IAAU,MAAM,IAAA,KAAS,UAAA,IAAc,MAAM,IAAA,KAAS,OAAA,IAAW,MAAM,IAAA,KAAS,UAAA,IAAc,MAAM,IAAA,KAAS,OAAA;AACpM,MAAA,IAAI,CAAC,SAAA,EAAW,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,GAAI,IAAA;AAAA,IACrC;AACA,IAAA,IAAI,MAAM,IAAA,KAAS,MAAA,IAAU,MAAM,IAAA,IAAQ,KAAA,CAAM,QAAS,KAAA,CAAc,IAAI,KAAK,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,IAAK,OAAO,KAAK,KAAA,CAAM,IAAI,MAAM,QAAA,EAAU;AACzI,MAAA,KAAA,MAAW,GAAA,IAAQ,MAAc,IAAA,EAAM;AACrC,QAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,EAAG,qBAAA,CAAsB,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG,GAAA,CAAI,MAAiB,CAAA;AAAA,MAC9F;AAAA,IACF,CAAA,MAAA,IAAA,CAAY,MAAM,IAAA,KAAS,OAAA,IAAW,MAAM,IAAA,KAAS,aAAA,KAAkB,KAAA,CAAM,IAAA,IAAQ,KAAA,CAAM,OAAA,CAAS,MAAc,MAAM,CAAA,IAAK,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,IAAK,OAAO,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,KAAM,QAAA,EAAU;AACrL,MAAA,qBAAA,CAAsB,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAI,MAAc,MAAiB,CAAA;AAAA,IAC1E,WAAW,KAAA,CAAM,IAAA,KAAS,OAAA,IAAW,KAAA,CAAM,QAAQ,KAAA,CAAM,OAAA,CAAS,KAAA,CAAc,MAAM,KAAK,KAAA,CAAM,OAAA,CAAQ,KAAK,KAAA,CAAM,IAAI,CAAC,CAAA,EAAG;AAC1H,MAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG;AACnC,QAAA,IAAI,QAAQ,OAAO,IAAA,KAAS,UAAU,qBAAA,CAAsB,IAAA,EAAO,MAAc,MAAiB,CAAA;AAAA,MACpG;AAAA,IACF,WAAW,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,KAAA,CAAM,QAAQ,KAAA,CAAM,OAAA,CAAS,KAAA,CAAc,MAAM,KAAK,KAAA,CAAM,OAAA,CAAQ,KAAK,KAAA,CAAM,IAAI,CAAC,CAAA,EAAG;AAC3H,MAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG;AACnC,QAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACvC,QAAA,MAAM,YAAA,GAAe,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,SAAA;AACvC,QAAA,IAAI,CAAC,YAAA,EAAc;AACnB,QAAA,MAAM,QAAA,GAAY,MAAc,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAW,CAAA,CAAE,SAAS,YAAY,CAAA;AAC/E,QAAA,IAAI,CAAC,QAAA,IAAY,CAAC,MAAM,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA,EAAG;AAClD,QAAA,MAAM,MAAA,GAAS,KAAK,IAAA,IAAQ,OAAO,KAAK,IAAA,KAAS,QAAA,GAAW,KAAK,IAAA,GAAO,IAAA;AACxE,QAAA,qBAAA,CAAsB,MAAA,EAAQ,SAAS,MAAiB,CAAA;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AACF;AAMA,eAAe,eAAA,CACb,MAAA,EACA,SAAA,EACA,GAAA,EACe;AACf,EAAA,MAAM,MAAA,GAAS,MAAMC,uCAAA,CAAsB,MAAA,EAAQ,SAAA,EAAW;AAAA,IAC5D,MAAM,GAAA,CAAI,IAAA;AAAA,IACV,KAAK,GAAA,CAAI,GAAA;AAAA,IACT,UAAU,GAAA,CAAI,QAAA;AAAA,IACd,QAAQ,GAAA,CAAI;AAAA,GACb,CAAA;AACD,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,KAAA,IAAS,eAAe,CAAA;AAAA,EACjD;AAGA,EAAA,IAAI,IAAI,QAAA,EAAU;AAChB,IAAA,GAAA,CAAI,EAAA,CAAG,iBAAiB,EAAE,QAAA,EAAU,IAAI,QAAA,EAAU,MAAA,EAAQ,IAAI,IAAA,EAAM,EAAA,IAAM,IAAI,IAAA,EAAM,GAAA,CAAI,MAAM,IAAA,EAAM,YAAA,EAAc,IAAI,IAAA,EAAM,IAAA,KAAS,eAAe,CAAA;AAAA,EACtJ;AACF;AAMO,SAAS,oBAAoB,GAAA,EAAkB;AACpD,EAAA,OAAO,OAAO,KAAA,KASR;AACJ,IAAA,MAAM,EAAE,YAAY,KAAA,EAAO,IAAA,EAAM,OAAO,IAAA,EAAM,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAM,GAAI,KAAA;AACvE,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAGzC,IAAA,IAAI,MAAA,CAAO,OAAO,UAAA,EAAY;AAC5B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,UAAA,EAAY;AAC1C,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,MAAA;AAAA,UACX;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,KAAA,IAAS,CAAC,CAAC,GAAA,CAAI,IAAA;AAG/B,IAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,EAAA,CAAG,IAAA,CAAK;AAAA,MAC/B,UAAA;AAAA,MACA,KAAA,EAAO,SAAS,EAAC;AAAA,MACjB,IAAA;AAAA,MACA,OAAO,KAAA,IAAS,EAAA;AAAA,MAChB,MAAM,IAAA,IAAQ,CAAA;AAAA,MACd,OAAO,KAAA,IAAS,CAAA;AAAA,MAChB,UAAU,GAAA,CAAI,QAAA;AAAA,MACd,MAAA;AAAA,MACA,KAAA,EAAO;AAAA,KACR,CAAA;AAGD,IAAA,IAAI,MAAA,CAAO,OAAO,SAAA,EAAW;AAC3B,MAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAC7B,QAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,SAAA,EAAW;AACzC,UAAA,MAAM,IAAA,CAAK;AAAA,YACT,UAAA;AAAA,YACA,GAAA;AAAA,YACA,KAAK,GAAA,CAAI,GAAA;AAAA,YACT,MAAM,GAAA,CAAI,IAAA;AAAA,YACV,UAAU,GAAA,CAAI,QAAA;AAAA,YACd,SAAA,EAAW;AAAA,WACZ,CAAA;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;AAEO,SAAS,wBAAwB,GAAA,EAAkB;AACxD,EAAA,OAAO,OAAO,KAAA,KAMR;AACJ,IAAA,MAAM,EAAE,UAAA,EAAY,EAAA,EAAI,KAAA,EAAO,MAAA,EAAQ,OAAM,GAAI,KAAA;AACjD,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAEzC,IAAA,MAAM,OAAA,GAAU,KAAA,IAAS,CAAC,CAAC,GAAA,CAAI,IAAA;AAE/B,IAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,QAAA,CAAS;AAAA,MAChC,UAAA;AAAA,MACA,EAAA;AAAA,MACA,OAAO,KAAA,IAAS,CAAA;AAAA,MAChB,UAAU,GAAA,CAAI,QAAA;AAAA,MACd,MAAA;AAAA,MACA,KAAA,EAAO;AAAA,KACR,CAAA;AAED,IAAA,IAAI,CAAC,KAAK,MAAM,IAAI,MAAM,CAAA,oBAAA,EAAuB,UAAU,CAAA,CAAA,EAAI,EAAE,CAAA,CAAE,CAAA;AAGnE,IAAA,IAAI,MAAA,CAAO,OAAO,SAAA,EAAW;AAC3B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,SAAA,EAAW;AACzC,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,GAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,MAAA;AAAA,UACX;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AACF;AAEO,SAAS,sBAAsB,GAAA,EAAkB;AACtD,EAAA,OAAO,OAAO,KAAA,KAKR;AACJ,IAAA,MAAM,EAAE,UAAA,EAAY,IAAA,EAAM,KAAA,EAAO,QAAO,GAAI,KAAA;AAC5C,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,QAAA,EAAU,GAAG,CAAA;AAG3C,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,kBAAA,CAAmB,UAAU,CAAA;AACzD,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAGnC,IAAA,IAAI,MAAA,CAAO,YAAA,IAAgB,GAAA,CAAI,QAAA,EAAU;AACvC,MAAA,SAAA,CAAU,WAAW,GAAA,CAAI,QAAA;AAAA,IAC3B;AAGA,IAAA,IAAI,MAAA,CAAO,OAAO,cAAA,EAAgB;AAChC,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,cAAA,EAAgB;AAC9C,QAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK;AAAA,UAC5B,UAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW;AAAA,SACZ,CAAA;AACD,QAAA,IAAI,UAAA,EAAY,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,UAAU,CAAA;AAAA,MACrD;AAAA,IACF;AAGA,IAAA,IAAI,MAAA,CAAO,OAAO,YAAA,EAAc;AAC9B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,YAAA,EAAc;AAC5C,QAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK;AAAA,UAC5B,UAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW;AAAA,SACZ,CAAA;AACD,QAAA,IAAI,UAAA,EAAY,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,UAAU,CAAA;AAAA,MACrD;AAAA,IACF;AAGA,IAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,MAC9B,UAAA;AAAA,MACA,IAAA,EAAM,SAAA;AAAA,MACN,OAAO,KAAA,IAAS,CAAA;AAAA,MAChB,UAAU,GAAA,CAAI,QAAA;AAAA,MACd;AAAA,KACD,CAAA;AAGD,IAAA,IAAI,MAAA,CAAO,OAAO,WAAA,EAAa;AAC7B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,WAAA,EAAa;AAC3C,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,GAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW;AAAA,SACZ,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,MAAM,cAAA,CAAe,GAAA,EAAK,eAAA,CAAgB,UAAA,EAAY,QAAQ,CAAA,EAAG;AAAA,MAC/D,UAAA;AAAA,MACA,IAAA,EAAM,GAAA;AAAA,MACN,SAAA,EAAW;AAAA,KACZ,CAAA;AAED,IAAA,OAAO,EAAE,GAAA,EAAI;AAAA,EACf,CAAA;AACF;AAEO,SAAS,sBAAsB,GAAA,EAAkB;AACtD,EAAA,OAAO,OAAO,KAAA,KAOR;AACJ,IAAA,MAAM,EAAE,UAAA,EAAY,EAAA,EAAI,MAAM,KAAA,EAAO,MAAA,EAAQ,eAAc,GAAI,KAAA;AAC/D,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,QAAA,EAAU,GAAG,CAAA;AAG3C,IAAA,MAAM,WAAA,GAAc,MAAM,GAAA,CAAI,EAAA,CAAG,QAAA,CAAS;AAAA,MACxC,UAAA;AAAA,MACA,EAAA;AAAA,MACA,UAAU,GAAA,CAAI,QAAA;AAAA,MACd,KAAA,EAAO;AAAA,KACR,CAAA;AAED,IAAA,IAAI,CAAC,WAAA;AACH,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,UAAU,CAAA,CAAA,EAAI,EAAE,CAAA,CAAE,CAAA;AAG3D,IAAA,IAAI,aAAA,IAAkB,WAAA,CAAoC,SAAA,IAAa,aAAA,KAAmB,YAAoC,SAAA,EAAW;AACvI,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8CAAA,EAAiD,aAAa,CAAA,qBAAA,EAAyB,WAAA,CAAoC,SAAS,CAAA,CAAE,CAAA;AAAA,IACxJ;AAGA,IAAA,qBAAA,CAAsB,IAAA,EAAa,OAAO,MAAa,CAAA;AAGvD,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,kBAAA,CAAmB,UAAU,CAAA;AACzD,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAGnC,IAAA,IAAI,MAAA,CAAO,YAAA,IAAgB,GAAA,CAAI,QAAA,EAAU;AACvC,MAAA,SAAA,CAAU,WAAW,GAAA,CAAI,QAAA;AAAA,IAC3B;AAGA,IAAA,IAAI,MAAA,CAAO,OAAO,cAAA,EAAgB;AAChC,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,cAAA,EAAgB;AAC9C,QAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK;AAAA,UAC5B,UAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,WAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,QAAA;AAAA,UACX;AAAA,SACD,CAAA;AACD,QAAA,IAAI,UAAA,EAAY,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,UAAU,CAAA;AAAA,MACrD;AAAA,IACF;AAGA,IAAA,IAAI,MAAA,CAAO,OAAO,YAAA,EAAc;AAC9B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,YAAA,EAAc;AAC5C,QAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK;AAAA,UAC5B,UAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,WAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,QAAA;AAAA,UACX;AAAA,SACD,CAAA;AACD,QAAA,IAAI,UAAA,EAAY,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,UAAU,CAAA;AAAA,MACrD;AAAA,IACF;AAGA,IAAA,MAAM,UAAW,GAAA,CAAI,GAAA,IAAO,OAAQ,GAAA,CAAI,IAAY,OAAA,EAAS,GAAA,KAAQ,UAAA,IAAe,GAAA,CAAI,IAAY,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA,KAAM,MAAA,IAAY,MAAc,KAAA,KAAU,IAAA;AACnK,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,QAAA,EAAU,MAAA,KAAW,IAAA;AACnD,IAAA,MAAM,UAAA,GAAe,GAAA,CAAI,GAAA,EAAa,KAAA,EAAO,QAAA,KAAa,MAAA,IAAa,GAAA,CAAI,GAAA,EAAa,GAAA,EAAK,QAAA,CAAS,eAAe,CAAA,IAAO,MAAc,QAAA,KAAa,IAAA;AAEvJ,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI,kBAAkB,OAAA,EAAS;AAG7B,MAAA,MAAM,GAAA,CAAI,GAAG,aAAA,CAAc;AAAA,QACzB,UAAA;AAAA,QACA,UAAA,EAAY,EAAA;AAAA,QACZ,IAAA,EAAM,SAAA;AAAA,QACN,MAAA,EAAQ,OAAA;AAAA,QACR,QAAA,EAAU,UAAA;AAAA,QACV,SAAA,EAAW,IAAI,IAAA,EAAM,EAAA;AAAA,QACrB,UAAU,GAAA,CAAI;AAAA,OACf,CAAA;AAED,MAAA,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,QAAA,CAAS,EAAE,UAAA,EAAY,EAAA,EAAI,QAAA,EAAU,GAAA,CAAI,QAAA,EAAU,KAAA,EAAO,IAAA,EAAM,CAAA;AAAA,IACrF,WAAW,cAAA,EAAgB;AAEzB,MAAA,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,QACxB,UAAA;AAAA,QACA,EAAA;AAAA,QACA,IAAA,EAAM,EAAE,GAAG,SAAA,EAAW,QAAQ,WAAA,EAAY;AAAA,QAC1C,OAAO,KAAA,IAAS,CAAA;AAAA,QAChB,UAAU,GAAA,CAAI,QAAA;AAAA,QACd;AAAA,OACD,CAAA;AACD,MAAA,MAAM,GAAA,CAAI,GAAG,aAAA,CAAc;AAAA,QACzB,UAAA;AAAA,QACA,UAAA,EAAY,EAAA;AAAA,QACZ,IAAA,EAAM,SAAA;AAAA,QACN,MAAA,EAAQ,WAAA;AAAA,QACR,SAAA,EAAW,IAAI,IAAA,EAAM,EAAA;AAAA,QACrB,UAAU,GAAA,CAAI;AAAA,OACf,CAAA;AAAA,IACH,CAAA,MAAO;AAEL,MAAA,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,QACxB,UAAA;AAAA,QACA,EAAA;AAAA,QACA,IAAA,EAAM,SAAA;AAAA,QACN,OAAO,KAAA,IAAS,CAAA;AAAA,QAChB,UAAU,GAAA,CAAI,QAAA;AAAA,QACd;AAAA,OACD,CAAA;AAAA,IACH;AAGA,IAAA,IAAI,MAAA,CAAO,OAAO,WAAA,EAAa;AAC7B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,WAAA,EAAa;AAC3C,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,GAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,WAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,QAAA;AAAA,UACX;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,MAAM,cAAA,CAAe,GAAA,EAAK,eAAA,CAAgB,UAAA,EAAY,QAAQ,CAAA,EAAG;AAAA,MAC/D,UAAA;AAAA,MACA,IAAA,EAAM,GAAA;AAAA,MACN,YAAA,EAAc,WAAA;AAAA,MACd,SAAA,EAAW;AAAA,KACZ,CAAA;AAED,IAAA,OAAO,EAAE,GAAA,EAAI;AAAA,EACf,CAAA;AACF;AAEO,SAAS,sBAAsB,GAAA,EAAkB;AACtD,EAAA,OAAO,OAAO,KAAA,KAA8C;AAC1D,IAAA,MAAM,EAAE,UAAA,EAAY,EAAA,EAAG,GAAI,KAAA;AAC3B,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,QAAA,EAAU,GAAG,CAAA;AAG3C,IAAA,MAAM,WAAA,GAAc,MAAM,GAAA,CAAI,EAAA,CAAG,QAAA,CAAS;AAAA,MACxC,UAAA;AAAA,MACA,EAAA;AAAA,MACA,UAAU,GAAA,CAAI,QAAA;AAAA,MACd,KAAA,EAAO;AAAA,KACR,CAAA;AAED,IAAA,IAAI,CAAC,WAAA;AACH,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,UAAU,CAAA,CAAA,EAAI,EAAE,CAAA,CAAE,CAAA;AAG3D,IAAA,IAAI,MAAA,CAAO,OAAO,YAAA,EAAc;AAC9B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,YAAA,EAAc;AAC5C,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,GAAA,EAAK,WAAA;AAAA,UACL,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,QAAA;AAAA,UACX;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAGA,IAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,MAC9B,UAAA;AAAA,MACA,EAAA;AAAA,MACA,UAAU,GAAA,CAAI;AAAA,KACf,CAAA;AAGD,IAAA,IAAI,MAAA,CAAO,OAAO,WAAA,EAAa;AAC7B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,WAAA,EAAa;AAC3C,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,GAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,QAAA;AAAA,UACX;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,MAAM,cAAA,CAAe,GAAA,EAAK,eAAA,CAAgB,UAAA,EAAY,QAAQ,CAAA,EAAG;AAAA,MAC/D,UAAA;AAAA,MACA,IAAA,EAAM,GAAA;AAAA,MACN,YAAA,EAAc,WAAA;AAAA,MACd,SAAA,EAAW;AAAA,KACZ,CAAA;AAED,IAAA,OAAO,EAAE,GAAA,EAAK,OAAA,EAAS,sBAAA,EAAuB;AAAA,EAChD,CAAA;AACF;AAEO,SAAS,qBAAqB,GAAA,EAAkB;AACrD,EAAA,OAAO,OAAO,KAAA,KAA+D;AAC3E,IAAA,MAAM,EAAE,UAAA,EAAY,KAAA,EAAM,GAAI,KAAA;AAC9B,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAEzC,IAAA,MAAM,SAAA,GAAY,MAAM,GAAA,CAAI,EAAA,CAAG,KAAA,CAAM;AAAA,MACnC,UAAA;AAAA,MACA,KAAA,EAAO,SAAS,EAAC;AAAA,MACjB,UAAU,GAAA,CAAI;AAAA,KACf,CAAA;AAED,IAAA,OAAO,EAAE,SAAA,EAAU;AAAA,EACrB,CAAA;AACF;;;AC5hBA,eAAe,qBAAA,CACb,MAAA,EACA,SAAA,EACA,GAAA,EACe;AACf,EAAA,MAAM,MAAA,GAAS,MAAMC,mCAAA,CAAwB,MAAA,EAAQ,SAAA,EAAW;AAAA,IAC9D,MAAM,GAAA,CAAI,IAAA;AAAA,IACV,KAAK,GAAA,CAAI,GAAA;AAAA,IACT,UAAU,GAAA,CAAI;AAAA,GACf,CAAA;AACD,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,KAAA,IAAS,eAAe,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,IAAI,QAAA,EAAU;AAChB,IAAA,GAAA,CAAI,EAAA,CAAG,iBAAiB,EAAE,QAAA,EAAU,IAAI,QAAA,EAAU,MAAA,EAAQ,IAAI,IAAA,EAAM,EAAA,IAAM,IAAI,IAAA,EAAM,GAAA,CAAI,MAAM,IAAA,EAAM,YAAA,EAAc,IAAI,IAAA,EAAM,IAAA,KAAS,eAAe,CAAA;AAAA,EACtJ;AACF;AAMO,SAAS,oBAAoB,GAAA,EAAkB;AACpD,EAAA,MAAM,SAA8B,EAAC;AACrC,EAAA,MAAM,WAAA,GAAc,GAAA,CAAI,QAAA,CAAS,cAAA,EAAe;AAEhD,EAAA,KAAA,MAAW,cAAc,WAAA,EAAa;AACpC,IAAA,MAAM,OAAO,UAAA,CAAW,IAAA;AAExB,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI;AAAA,MACb,IAAA,EAAM,oBAAoB,GAAG,CAAA;AAAA,MAC7B,QAAA,EAAU,wBAAwB,GAAG,CAAA;AAAA,MACrC,MAAA,EAAQ,sBAAsB,GAAG,CAAA;AAAA,MACjC,MAAA,EAAQ,sBAAsB,GAAG,CAAA;AAAA,MACjC,MAAA,EAAQ,sBAAsB,GAAG,CAAA;AAAA,MACjC,KAAA,EAAO,qBAAqB,GAAG;AAAA,KACjC;AAAA,EACF;AAGA,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,QAAA,CAAS,UAAA,EAAW;AACxC,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AAEpB,IAAA,MAAA,CAAO,CAAA,SAAA,EAAY,IAAI,CAAA,CAAE,CAAA,GAAI;AAAA,MAC3B,KAAK,YAAY;AACf,QAAA,MAAM,qBAAA,CAAsB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAE/C,QAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,OAAA,CAAQ;AAAA,UAC/B,UAAA,EAAY,YAAY,IAAI,CAAA,CAAA;AAAA,UAC5B,OAAO,EAAC;AAAA,UACR,UAAU,GAAA,CAAI;AAAA,SACf,CAAA;AACD,QAAA,OAAO,GAAA;AAAA,MACT,CAAA;AAAA,MACA,MAAA,EAAQ,OAAO,KAAA,KAAyC;AACtD,QAAA,MAAM,qBAAA,CAAsB,MAAA,EAAQ,QAAA,EAAU,GAAG,CAAA;AAEjD,QAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,YAAA,CAAa,IAAI,CAAA;AAC7C,QAAA,MAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AAEzC,QAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,EAAA,CAAG,OAAA,CAAQ;AAAA,UACpC,UAAA,EAAY,YAAY,IAAI,CAAA,CAAA;AAAA,UAC5B,OAAO,EAAC;AAAA,UACR,UAAU,GAAA,CAAI;AAAA,SACf,CAAA;AAED,QAAA,IAAI,GAAA;AACJ,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,YACxB,UAAA,EAAY,YAAY,IAAI,CAAA,CAAA;AAAA,YAC5B,IAAI,QAAA,CAAS,EAAA;AAAA,YACb,IAAA,EAAM,SAAA;AAAA,YACN,UAAU,GAAA,CAAI;AAAA,WACf,CAAA;AAAA,QACH,CAAA,MAAO;AACL,UAAA,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,YACxB,UAAA,EAAY,YAAY,IAAI,CAAA,CAAA;AAAA,YAC5B,IAAA,EAAM,EAAE,GAAG,SAAA,EAAW,IAAI,IAAA,EAAK;AAAA,YAC/B,UAAU,GAAA,CAAI;AAAA,WACf,CAAA;AAAA,QACH;AAEA,QAAA,OAAO,GAAA;AAAA,MACT;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAyDO,SAAS,iBAAiB,GAAA,EAA8B;AAE7D,EAAA,MAAM,SAAA,GAAY,GAAA,CAAI,QAAA,EAAU,MAAA,EAAQ,SAAA;AACxC,EAAA,IAAI,SAAA,EAAW,gBAAgB,KAAA,EAAO;AACpC,IAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,EACxC;AAEA,EAAA,OAAO,oBAAoB,GAAG,CAAA;AAChC","file":"chunk-HVCUIII2.cjs","sourcesContent":["import type { BaseAdapter } from \"../../registry/types.js\";\nimport type { User, Request } from \"../../hooks/types.js\";\nimport {\n validateApiKey,\n extractApiKeyFromRequest,\n createApiKeyContext,\n} from \"../../auth/api-key.js\";\nimport { createWebhookService } from \"../../webhooks/index.js\";\n\n// ============================================================================\n// Context Types\n// ============================================================================\n\nexport interface ApiKeyContext {\n userId: string;\n user: Partial<User>;\n permissions: string[];\n apiKeyId: string;\n tenantId?: string;\n role?: string;\n}\n\nexport interface KyroContext {\n db: BaseAdapter;\n registry: any;\n user?: User;\n tenantID?: string;\n req: Request;\n apiKey?: ApiKeyContext;\n webhookService?: ReturnType<typeof createWebhookService>;\n settings?: Record<string, any>;\n [key: string]: any;\n}\n\n// ============================================================================\n// Context Factory\n// ============================================================================\n\nexport async function createContext(options: {\n db: BaseAdapter;\n registry: any;\n req: Request;\n user?: User;\n tenantID?: string;\n settings?: Record<string, any>;\n}): Promise<KyroContext> {\n const webhookService = createWebhookService(options.db);\n\n const baseContext: KyroContext = {\n db: options.db,\n registry: options.registry,\n req: options.req,\n user: options.user,\n tenantID: options.tenantID,\n webhookService,\n settings: options.settings,\n };\n\n const apiKeyRaw = extractApiKeyFromRequest(options.req as any);\n if (apiKeyRaw) {\n const result = await validateApiKey(apiKeyRaw, options.db, async (userId) => {\n try {\n const user = await options.db.findByID({ collection: 'users', id: userId });\n return user || null;\n } catch {\n return null;\n }\n });\n if (result.valid) {\n baseContext.user = (result.user as User) || options.user;\n baseContext.tenantID = result.tenantId || options.tenantID;\n baseContext.apiKey = createApiKeyContext(result) as ApiKeyContext;\n }\n }\n\n return baseContext;\n}\n","import type {\n FindArgs,\n CreateArgs,\n UpdateArgs,\n DeleteArgs,\n} from \"../../registry/types.js\";\nimport { runHooks } from \"../../hooks/types.js\";\nimport { checkCollectionAccess, checkGlobalAccess } from \"../../access/checker.js\";\nimport type { KyroContext } from \"./context.js\";\nimport type { Field } from \"../../fields/types.js\";\nimport { WEBHOOK_EVENTS, type WebhookEvent } from \"../../webhooks/types.js\";\n\nconst COLLECTION_EVENT_MAP: Record<\n string,\n { create: WebhookEvent; update: WebhookEvent; delete: WebhookEvent }\n> = {\n _media: {\n create: WEBHOOK_EVENTS.MEDIA_UPLOAD,\n update: WEBHOOK_EVENTS.MEDIA_UPLOAD,\n delete: WEBHOOK_EVENTS.MEDIA_DELETE,\n },\n};\n\nfunction getWebhookEvent(\n collection: string,\n operation: \"create\" | \"update\" | \"delete\",\n): WebhookEvent {\n const mapped = COLLECTION_EVENT_MAP[collection];\n if (mapped) return mapped[operation];\n return `collection.${operation}` as WebhookEvent;\n}\n\nasync function triggerWebhook(\n ctx: KyroContext,\n event: WebhookEvent,\n payload: {\n collection: string;\n data: unknown;\n previousData?: unknown;\n operation: \"create\" | \"update\" | \"delete\";\n },\n) {\n if (!ctx.webhookService) return;\n try {\n await ctx.webhookService.trigger(event, {\n collection: payload.collection,\n operation: payload.operation,\n data: payload.data,\n previousData: payload.previousData,\n user: ctx.user\n ? { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role }\n : undefined,\n tenantId: ctx.tenantID,\n });\n } catch (err) {\n console.error(`[Webhook] Failed to trigger ${event}:`, err);\n }\n}\n\n// ============================================================================\n// Data normalization helpers\n// ============================================================================\n\nfunction normalizeEmptyStrings(data: any, fields: Field[]): void {\n if (!data || typeof data !== 'object') return;\n for (const field of fields) {\n if (!field.name || !(field.name in data)) continue;\n const val = data[field.name];\n if (val === \"\") {\n const isTextual = field.type === 'text' || field.type === 'textarea' || field.type === 'code' || field.type === 'markdown' || field.type === 'email' || field.type === 'password' || field.type === 'color';\n if (!isTextual) data[field.name] = null;\n }\n if (field.type === 'tabs' && field.name && Array.isArray((field as any).tabs) && data[field.name] && typeof data[field.name] === 'object') {\n for (const tab of (field as any).tabs) {\n if (Array.isArray(tab.fields)) normalizeEmptyStrings(data[field.name], tab.fields as Field[]);\n }\n } else if ((field.type === 'group' || field.type === 'collapsible') && field.name && Array.isArray((field as any).fields) && data[field.name] && typeof data[field.name] === 'object') {\n normalizeEmptyStrings(data[field.name], (field as any).fields as Field[]);\n } else if (field.type === 'array' && field.name && Array.isArray((field as any).fields) && Array.isArray(data[field.name])) {\n for (const item of data[field.name]) {\n if (item && typeof item === 'object') normalizeEmptyStrings(item, (field as any).fields as Field[]);\n }\n } else if (field.type === 'blocks' && field.name && Array.isArray((field as any).blocks) && Array.isArray(data[field.name])) {\n for (const item of data[field.name]) {\n if (!item || typeof item !== 'object') continue;\n const blockTypeStr = item.type || item.blockType;\n if (!blockTypeStr) continue;\n const blockDef = (field as any).blocks.find((b: any) => b.slug === blockTypeStr);\n if (!blockDef || !Array.isArray(blockDef.fields)) continue;\n const target = item.data && typeof item.data === 'object' ? item.data : item;\n normalizeEmptyStrings(target, blockDef.fields as Field[]);\n }\n }\n }\n}\n\n// ============================================================================\n// Access Check Helper\n// ============================================================================\n\nasync function checkTRPCAccess(\n config: { access?: any; slug: string },\n operation: \"read\" | \"create\" | \"update\" | \"delete\",\n ctx: KyroContext,\n): Promise<void> {\n const result = await checkCollectionAccess(config, operation, {\n user: ctx.user,\n req: ctx.req,\n tenantID: ctx.tenantID,\n apiKey: ctx.apiKey,\n });\n if (!result.allowed) {\n throw new Error(result.error || \"Access denied\");\n }\n\n // Set tenant context\n if (ctx.tenantID) {\n ctx.db.setTenantContext({ tenantId: ctx.tenantID, userId: ctx.user?.id ?? '', role: ctx.user?.role, isSuperAdmin: ctx.user?.role === 'super_admin' });\n }\n}\n\n// ============================================================================\n// CRUD Procedure Builders\n// ============================================================================\n\nexport function createFindProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n where?: Record<string, any>;\n sort?: string;\n limit?: number;\n page?: number;\n depth?: number;\n select?: string[];\n draft?: boolean;\n }) => {\n const { collection, where, sort, limit, page, depth, select, draft } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"read\", ctx);\n\n // Run beforeRead hooks\n if (config.hooks?.beforeRead) {\n for (const hook of config.hooks.beforeRead) {\n await hook({\n collection,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"read\",\n where,\n });\n }\n }\n\n const isDraft = draft ?? !!ctx.user;\n\n // Execute query\n const result = await ctx.db.find({\n collection,\n where: where || {},\n sort,\n limit: limit || 10,\n page: page || 1,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n draft: isDraft,\n });\n\n // Run afterRead hooks\n if (config.hooks?.afterRead) {\n for (const doc of result.docs) {\n for (const hook of config.hooks.afterRead) {\n await hook({\n collection,\n doc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"read\",\n });\n }\n }\n }\n\n return result;\n };\n}\n\nexport function createFindByIDProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n id: string;\n depth?: number;\n select?: string[];\n draft?: boolean;\n }) => {\n const { collection, id, depth, select, draft } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"read\", ctx);\n\n const isDraft = draft ?? !!ctx.user;\n\n const doc = await ctx.db.findByID({\n collection,\n id,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n draft: isDraft,\n });\n\n if (!doc) throw new Error(`Document not found: ${collection}/${id}`);\n\n // Run afterRead hooks\n if (config.hooks?.afterRead) {\n for (const hook of config.hooks.afterRead) {\n await hook({\n collection,\n doc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"read\",\n id,\n });\n }\n }\n\n return doc;\n };\n}\n\nexport function createCreateProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n }) => {\n const { collection, data, depth, select } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"create\", ctx);\n\n // Validate with Zod\n const schema = ctx.registry.getCreateZodSchema(collection);\n const validated = schema.parse(data);\n\n // Add tenantID if scoped\n if (config.tenantScoped && ctx.tenantID) {\n validated.tenantID = ctx.tenantID;\n }\n\n // Run beforeValidate hooks\n if (config.hooks?.beforeValidate) {\n for (const hook of config.hooks.beforeValidate) {\n const hookResult = await hook({\n collection,\n data: validated,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"create\",\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Run beforeChange hooks\n if (config.hooks?.beforeChange) {\n for (const hook of config.hooks.beforeChange) {\n const hookResult = await hook({\n collection,\n data: validated,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"create\",\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Execute create\n const doc = await ctx.db.create({\n collection,\n data: validated,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n });\n\n // Run afterChange hooks\n if (config.hooks?.afterChange) {\n for (const hook of config.hooks.afterChange) {\n await hook({\n collection,\n doc,\n data: validated,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"create\",\n });\n }\n }\n\n await triggerWebhook(ctx, getWebhookEvent(collection, \"create\"), {\n collection,\n data: doc,\n operation: \"create\",\n });\n\n return { doc };\n };\n}\n\nexport function createUpdateProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n id: string;\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n baseUpdatedAt?: string;\n }) => {\n const { collection, id, data, depth, select, baseUpdatedAt } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"update\", ctx);\n\n // Get original doc for hooks + conflict detection\n const originalDoc = await ctx.db.findByID({\n collection,\n id,\n tenantID: ctx.tenantID,\n draft: true,\n });\n\n if (!originalDoc)\n throw new Error(`Document not found: ${collection}/${id}`);\n\n // Revision conflict detection\n if (baseUpdatedAt && (originalDoc as Record<string, any>).updatedAt && baseUpdatedAt !== (originalDoc as Record<string, any>).updatedAt) {\n throw new Error(`Revision conflict: document has changed since ${baseUpdatedAt}. Current updatedAt: ${(originalDoc as Record<string, any>).updatedAt}`);\n }\n\n // Normalize empty strings for non-textual field types\n normalizeEmptyStrings(data as any, config.fields as any);\n\n // Validate with Zod\n const schema = ctx.registry.getUpdateZodSchema(collection);\n const validated = schema.parse(data);\n\n // Add tenantID if scoped\n if (config.tenantScoped && ctx.tenantID) {\n validated.tenantID = ctx.tenantID;\n }\n\n // Run beforeValidate hooks\n if (config.hooks?.beforeValidate) {\n for (const hook of config.hooks.beforeValidate) {\n const hookResult = await hook({\n collection,\n data: validated,\n originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"update\",\n id,\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Run beforeChange hooks\n if (config.hooks?.beforeChange) {\n for (const hook of config.hooks.beforeChange) {\n const hookResult = await hook({\n collection,\n data: validated,\n originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"update\",\n id,\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Determine if this is a draft save vs publish\n const isDraft = (ctx.req && typeof (ctx.req as any).headers?.get === \"function\" && (ctx.req as any).headers.get(\"x-draft\") === \"true\") || (input as any).draft === true;\n const isDraftEnabled = config.versions?.drafts === true;\n const isAutosave = ((ctx.req as any)?.query?.autosave === \"true\") || ((ctx.req as any)?.url?.includes(\"autosave=true\")) || (input as any).autosave === true;\n\n let doc;\n if (isDraftEnabled && isDraft) {\n // Draft save: versions table only\n // Autosave reuses a single version slot; manual draft creates a new version\n await ctx.db.createVersion({\n collection,\n documentId: id,\n data: validated,\n status: 'draft',\n autosave: isAutosave,\n createdBy: ctx.user?.id,\n tenantID: ctx.tenantID,\n });\n // Refetch merged doc\n doc = await ctx.db.findByID({ collection, id, tenantID: ctx.tenantID, draft: true });\n } else if (isDraftEnabled) {\n // Publish: main doc + versions table\n doc = await ctx.db.update({\n collection,\n id,\n data: { ...validated, status: 'published' },\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n });\n await ctx.db.createVersion({\n collection,\n documentId: id,\n data: validated,\n status: 'published',\n createdBy: ctx.user?.id,\n tenantID: ctx.tenantID,\n });\n } else {\n // No versions: direct update\n doc = await ctx.db.update({\n collection,\n id,\n data: validated,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n });\n }\n\n // Run afterChange hooks\n if (config.hooks?.afterChange) {\n for (const hook of config.hooks.afterChange) {\n await hook({\n collection,\n doc,\n data: validated,\n originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"update\",\n id,\n });\n }\n }\n\n await triggerWebhook(ctx, getWebhookEvent(collection, \"update\"), {\n collection,\n data: doc,\n previousData: originalDoc,\n operation: \"update\",\n });\n\n return { doc };\n };\n}\n\nexport function createDeleteProcedure(ctx: KyroContext) {\n return async (input: { collection: string; id: string }) => {\n const { collection, id } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"delete\", ctx);\n\n // Get original doc for hooks\n const originalDoc = await ctx.db.findByID({\n collection,\n id,\n tenantID: ctx.tenantID,\n draft: true,\n });\n\n if (!originalDoc)\n throw new Error(`Document not found: ${collection}/${id}`);\n\n // Run beforeDelete hooks\n if (config.hooks?.beforeDelete) {\n for (const hook of config.hooks.beforeDelete) {\n await hook({\n collection,\n doc: originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"delete\",\n id,\n });\n }\n }\n\n // Execute delete\n const doc = await ctx.db.delete({\n collection,\n id,\n tenantID: ctx.tenantID,\n });\n\n // Run afterDelete hooks\n if (config.hooks?.afterDelete) {\n for (const hook of config.hooks.afterDelete) {\n await hook({\n collection,\n doc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"delete\",\n id,\n });\n }\n }\n\n await triggerWebhook(ctx, getWebhookEvent(collection, \"delete\"), {\n collection,\n data: doc,\n previousData: originalDoc,\n operation: \"delete\",\n });\n\n return { doc, message: \"Deleted successfully\" };\n };\n}\n\nexport function createCountProcedure(ctx: KyroContext) {\n return async (input: { collection: string; where?: Record<string, any> }) => {\n const { collection, where } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"read\", ctx);\n\n const totalDocs = await ctx.db.count({\n collection,\n where: where || {},\n tenantID: ctx.tenantID,\n });\n\n return { totalDocs };\n };\n}\n","import type { KyroContext } from \"./context.js\";\nimport {\n createFindProcedure,\n createFindByIDProcedure,\n createCreateProcedure,\n createUpdateProcedure,\n createDeleteProcedure,\n createCountProcedure,\n} from \"./procedures.js\";\nimport { checkGlobalAccess as checkGlobalAccessShared } from \"../../access/checker.js\";\n\n// ============================================================================\n// Global Access Check Helper\n// ============================================================================\n\nasync function checkGlobalAccessTRPC(\n global: { access?: any; slug: string },\n operation: \"read\" | \"update\",\n ctx: KyroContext,\n): Promise<void> {\n const result = await checkGlobalAccessShared(global, operation, {\n user: ctx.user,\n req: ctx.req,\n tenantID: ctx.tenantID,\n });\n if (!result.allowed) {\n throw new Error(result.error || \"Access denied\");\n }\n\n if (ctx.tenantID) {\n ctx.db.setTenantContext({ tenantId: ctx.tenantID, userId: ctx.user?.id ?? '', role: ctx.user?.role, isSuperAdmin: ctx.user?.role === 'super_admin' });\n }\n}\n\n// ============================================================================\n// Dynamic Router Generator\n// ============================================================================\n\nexport function createDynamicRouter(ctx: KyroContext) {\n const router: Record<string, any> = {};\n const collections = ctx.registry.getCollections();\n\n for (const collection of collections) {\n const slug = collection.slug;\n\n router[slug] = {\n find: createFindProcedure(ctx),\n findByID: createFindByIDProcedure(ctx),\n create: createCreateProcedure(ctx),\n update: createUpdateProcedure(ctx),\n delete: createDeleteProcedure(ctx),\n count: createCountProcedure(ctx),\n };\n }\n\n // Add globals\n const globals = ctx.registry.getGlobals();\n for (const global of globals) {\n const slug = global.slug;\n\n router[`_globals_${slug}`] = {\n get: async () => {\n await checkGlobalAccessTRPC(global, \"read\", ctx);\n\n const doc = await ctx.db.findOne({\n collection: `_globals_${slug}`,\n where: {},\n tenantID: ctx.tenantID,\n });\n return doc;\n },\n update: async (input: { data: Record<string, any> }) => {\n await checkGlobalAccessTRPC(global, \"update\", ctx);\n\n const schema = ctx.registry.getZodSchema(slug);\n const validated = schema.parse(input.data);\n\n const existing = await ctx.db.findOne({\n collection: `_globals_${slug}`,\n where: {},\n tenantID: ctx.tenantID,\n });\n\n let doc;\n if (existing) {\n doc = await ctx.db.update({\n collection: `_globals_${slug}`,\n id: existing.id,\n data: validated,\n tenantID: ctx.tenantID,\n });\n } else {\n doc = await ctx.db.create({\n collection: `_globals_${slug}`,\n data: { ...validated, id: slug },\n tenantID: ctx.tenantID,\n });\n }\n\n return doc;\n },\n };\n }\n\n return router;\n}\n\n// ============================================================================\n// Typed Router Interface\n// ============================================================================\n\nexport interface KyroRouter {\n [collectionSlug: string]: {\n find: (input: {\n where?: Record<string, any>;\n sort?: string;\n limit?: number;\n page?: number;\n depth?: number;\n select?: string[];\n draft?: boolean;\n }) => Promise<{\n docs: any[];\n totalDocs: number;\n limit: number;\n totalPages: number;\n page: number;\n pagingCounter: number;\n hasPrevPage: boolean;\n hasNextPage: boolean;\n prevPage: number | null;\n nextPage: number | null;\n }>;\n findByID: (input: {\n id: string;\n depth?: number;\n select?: string[];\n draft?: boolean;\n }) => Promise<any>;\n create: (input: {\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n }) => Promise<{ doc: any }>;\n update: (input: {\n id: string;\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n baseUpdatedAt?: string;\n }) => Promise<{ doc: any }>;\n delete: (input: { id: string }) => Promise<{ doc: any; message: string }>;\n count: (input: {\n where?: Record<string, any>;\n }) => Promise<{ totalDocs: number }>;\n };\n}\n\n// ============================================================================\n// Server Entry\n// ============================================================================\n\nexport function createKyroServer(ctx: KyroContext): KyroRouter {\n // Check if tRPC is disabled in settings\n const apiAccess = ctx.settings?.access?.apiAccess;\n if (apiAccess?.trpcEnabled === false) {\n throw new Error(\"tRPC API is disabled\");\n }\n\n return createDynamicRouter(ctx) as KyroRouter;\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { hasPermission } from './chunk-L4EZKIEX.js';
1
2
  import { timingSafeEqual } from 'crypto';
2
3
 
3
4
  // src/access/types.ts
@@ -157,6 +158,110 @@ function generateApiKeyPrefix(key) {
157
158
  return key.substring(0, 8);
158
159
  }
159
160
 
160
- export { API_KEY_COLLECTION, createApiKeyContext, evaluateAccess, extractApiKeyFromRequest, generateApiKey, generateApiKeyPrefix, getWhereClause, hasApiKeyPermission, mergeWhereClauses, validateApiKey };
161
- //# sourceMappingURL=chunk-CJONKRHJ.js.map
162
- //# sourceMappingURL=chunk-CJONKRHJ.js.map
161
+ // src/access/checker.ts
162
+ function actionToPermission(operation) {
163
+ if (operation === "read") return "read";
164
+ if (operation === "create") return "create";
165
+ if (operation === "update") return "update";
166
+ return "delete";
167
+ }
168
+ function isDefaultAllowed(operation, defaultAccess) {
169
+ const levels = {
170
+ none: false,
171
+ read: operation === "read",
172
+ create: operation === "read" || operation === "create",
173
+ update: operation === "read" || operation === "create" || operation === "update",
174
+ delete: operation === "read" || operation === "create" || operation === "update" || operation === "delete",
175
+ admin: true
176
+ };
177
+ return levels[defaultAccess] || false;
178
+ }
179
+ async function checkCollectionAccess(config, operation, context, options = {}) {
180
+ const { user, req, tenantID, apiKey } = context;
181
+ const { enablePublicAccess = true, defaultAccess = "none" } = options;
182
+ const accessRule = config.access?.[operation];
183
+ if (accessRule) {
184
+ const allowed = await evaluateAccess(accessRule, {
185
+ req,
186
+ user,
187
+ tenantID
188
+ });
189
+ if (allowed === false) {
190
+ return { allowed: false, error: "Access denied", status: 403 };
191
+ }
192
+ if (typeof allowed === "object") {
193
+ return { allowed: true, extraWhere: allowed };
194
+ }
195
+ return { allowed: true };
196
+ }
197
+ if (apiKey?.permissions?.length > 0) {
198
+ const resource = config.slug;
199
+ const action = actionToPermission(operation);
200
+ const permission = `${resource}:${action}`;
201
+ if (!hasApiKeyPermission(apiKey.permissions, permission) && !hasApiKeyPermission(apiKey.permissions, `${resource}:admin`)) {
202
+ return { allowed: false, error: "Access denied: insufficient permissions", status: 403 };
203
+ }
204
+ return { allowed: true };
205
+ }
206
+ if (user) {
207
+ const resource = config.slug;
208
+ const action = actionToPermission(operation);
209
+ const permission = `${resource}:${action}`;
210
+ const userHas = hasPermission(
211
+ { id: user.id, email: user.email, role: user.role },
212
+ permission
213
+ );
214
+ const adminHas = hasPermission(
215
+ { id: user.id, email: user.email, role: user.role },
216
+ `${resource}:admin`
217
+ );
218
+ if (userHas || adminHas) {
219
+ return { allowed: true };
220
+ }
221
+ return { allowed: false, error: "Access denied: missing RBAC permission", status: 403 };
222
+ }
223
+ const defaultAllowed = isDefaultAllowed(operation, defaultAccess);
224
+ if (enablePublicAccess && defaultAllowed) {
225
+ return { allowed: true };
226
+ }
227
+ return { allowed: false, error: "Authentication required", status: 401 };
228
+ }
229
+ async function checkGlobalAccess(config, operation, context, options = {}) {
230
+ const { user, req, tenantID } = context;
231
+ const { enablePublicAccess = true } = options;
232
+ const accessRule = config.access?.[operation];
233
+ if (accessRule) {
234
+ const allowed = await evaluateAccess(accessRule, {
235
+ req,
236
+ user,
237
+ tenantID
238
+ });
239
+ if (allowed === false) {
240
+ return { allowed: false, error: "Access denied", status: 403 };
241
+ }
242
+ return { allowed: true };
243
+ }
244
+ if (user) {
245
+ const permission = `globals:${operation}`;
246
+ const userHas = hasPermission(
247
+ { id: user.id, email: user.email, role: user.role },
248
+ permission
249
+ );
250
+ const adminHas = hasPermission(
251
+ { id: user.id, email: user.email, role: user.role },
252
+ "globals:admin"
253
+ );
254
+ if (userHas || adminHas) {
255
+ return { allowed: true };
256
+ }
257
+ return { allowed: false, error: "Access denied: missing RBAC permission", status: 403 };
258
+ }
259
+ if (enablePublicAccess) {
260
+ return { allowed: true };
261
+ }
262
+ return { allowed: false, error: "Authentication required", status: 401 };
263
+ }
264
+
265
+ export { API_KEY_COLLECTION, checkCollectionAccess, checkGlobalAccess, createApiKeyContext, evaluateAccess, extractApiKeyFromRequest, generateApiKey, generateApiKeyPrefix, getWhereClause, mergeWhereClauses, validateApiKey };
266
+ //# sourceMappingURL=chunk-NZEUU7QB.js.map
267
+ //# sourceMappingURL=chunk-NZEUU7QB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/access/types.ts","../src/auth/api-key.ts","../src/access/checker.ts"],"names":[],"mappings":"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","file":"chunk-NZEUU7QB.js","sourcesContent":["import type { User, Request } from '../hooks/types.js';\n\n// ============================================================================\n// Access Control Types\n// ============================================================================\n\nexport interface WhereClause {\n [field: string]: any;\n}\n\nexport interface AccessArgs {\n req: Request;\n user?: User;\n data?: any;\n doc?: any;\n id?: string;\n tenantID?: string;\n context?: Record<string, any>;\n}\n\nexport type AccessControl = boolean | ((args: AccessArgs) => Promise<boolean | WhereClause> | boolean | WhereClause);\n\nexport interface CollectionAccess {\n create?: AccessControl;\n read?: AccessControl;\n update?: AccessControl;\n delete?: AccessControl;\n admin?: AccessControl;\n unlock?: AccessControl;\n readVersions?: AccessControl;\n}\n\nexport interface GlobalAccess {\n read?: AccessControl;\n update?: AccessControl;\n}\n\nexport interface FieldAccess {\n create?: AccessControl;\n read?: AccessControl;\n update?: AccessControl;\n}\n\n// ============================================================================\n// Access Control Evaluation\n// ============================================================================\n\nexport async function evaluateAccess(\n access: AccessControl,\n args: AccessArgs\n): Promise<boolean | WhereClause> {\n if (typeof access === 'boolean') {\n return access;\n }\n if (typeof access === 'function') {\n return await access(args);\n }\n return true;\n}\n\nexport function mergeWhereClauses(\n ...whereClauses: (WhereClause | boolean | undefined)[]\n): WhereClause {\n const result: WhereClause = {};\n for (const clause of whereClauses) {\n if (clause && typeof clause === 'object') {\n Object.assign(result, clause);\n }\n }\n return result;\n}\n\nexport function getWhereClause(\n access: AccessControl,\n args: AccessArgs\n): Promise<WhereClause | undefined> {\n return evaluateAccess(access, args).then(result => {\n if (result === true) return undefined;\n if (result === false) return { _id: { $eq: null } };\n return result;\n });\n}\n","import { timingSafeEqual } from \"crypto\";\nimport type { BaseAdapter } from \"../registry/types.js\";\nimport type { AuthUser, UserRole } from \"./types.js\";\n\nexport interface ApiKeyRecord {\n id: string;\n userId: string;\n name: string;\n key: string;\n keyPrefix: string;\n permissions: string[];\n lastUsedAt?: string;\n expiresAt?: string;\n createdAt: string;\n}\n\nexport interface ApiKeyValidationResult {\n valid: boolean;\n userId?: string;\n user?: Partial<AuthUser>;\n permissions?: string[];\n apiKeyId?: string;\n error?: string;\n tenantId?: string;\n role?: UserRole;\n}\n\nexport interface ApiKeyContext {\n userId: string;\n user: Partial<AuthUser>;\n permissions: string[];\n apiKeyId: string;\n tenantId?: string;\n role?: UserRole;\n}\n\nexport const API_KEY_COLLECTION = \"_api_keys\";\n\nfunction generateKeyPrefix(key: string): string {\n return key.substring(0, 8);\n}\n\nfunction constantTimeCompare(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n try {\n return timingSafeEqual(Buffer.from(a), Buffer.from(b));\n } catch {\n return false;\n }\n}\n\nexport async function validateApiKey(\n rawKey: string,\n db: BaseAdapter,\n userLookup?: (userId: string) => Promise<Partial<AuthUser> | null>,\n): Promise<ApiKeyValidationResult> {\n if (!rawKey || typeof rawKey !== \"string\") {\n return { valid: false, error: \"No API key provided\" };\n }\n\n if (!rawKey.startsWith(\"kyro_\")) {\n return { valid: false, error: \"Invalid API key format\" };\n }\n\n const keyPrefix = generateKeyPrefix(rawKey);\n\n try {\n const result = await db.find({\n collection: API_KEY_COLLECTION,\n where: { keyPrefix: { equals: keyPrefix } },\n limit: 100,\n page: 1,\n });\n\n if (!result.docs || result.docs.length === 0) {\n return { valid: false, error: \"Invalid API key\" };\n }\n\n let matchedKey: ApiKeyRecord | null = null;\n for (const doc of result.docs) {\n const record = doc as unknown as ApiKeyRecord;\n if (constantTimeCompare(record.key, rawKey)) {\n matchedKey = record;\n break;\n }\n }\n\n if (!matchedKey) {\n return { valid: false, error: \"Invalid API key\" };\n }\n\n if (matchedKey.expiresAt) {\n const expiresAt = new Date(matchedKey.expiresAt);\n if (expiresAt < new Date()) {\n return { valid: false, error: \"API key has expired\" };\n }\n }\n\n try {\n await db.update({\n collection: API_KEY_COLLECTION,\n id: matchedKey.id,\n data: { lastUsedAt: new Date().toISOString() },\n });\n } catch {\n // Non-critical: don't fail if lastUsedAt update fails\n }\n\n const user: Partial<AuthUser> = {\n id: matchedKey.userId,\n role: (matchedKey as any).role || \"author\",\n tenantId: (matchedKey as any).tenantId,\n };\n\n if (userLookup) {\n const dbUser = await userLookup(matchedKey.userId);\n if (dbUser) {\n Object.assign(user, dbUser);\n }\n }\n\n return {\n valid: true,\n userId: matchedKey.userId,\n user,\n permissions: matchedKey.permissions || [],\n apiKeyId: matchedKey.id,\n tenantId: user.tenantId,\n role: user.role,\n };\n } catch (error) {\n console.error(\"[ApiKey] Validation error:\", error);\n return { valid: false, error: \"Failed to validate API key\" };\n }\n}\n\nexport function extractApiKeyFromRequest(request: Request): string | null {\n const authHeader = request.headers.get(\"Authorization\");\n if (authHeader) {\n if (authHeader.startsWith(\"ApiKey \")) {\n return authHeader.slice(7).trim();\n }\n if (authHeader.startsWith(\"Bearer \")) {\n return null;\n }\n }\n\n const xApiKey = request.headers.get(\"X-API-Key\");\n if (xApiKey) {\n return xApiKey.trim();\n }\n\n return null;\n}\n\nexport function createApiKeyContext(\n result: ApiKeyValidationResult,\n): ApiKeyContext | null {\n if (!result.valid || !result.userId) {\n return null;\n }\n return {\n userId: result.userId,\n user: result.user || {},\n permissions: result.permissions || [],\n apiKeyId: result.apiKeyId || \"\",\n tenantId: result.tenantId,\n role: result.role,\n };\n}\n\nexport function hasApiKeyPermission(\n permissions: string[],\n required: string,\n): boolean {\n if (permissions.length === 0) return false;\n if (permissions.includes(\"*\")) return true;\n if (permissions.includes(required)) return true;\n\n const [resource, action] = required.split(\":\");\n if (permissions.includes(`${resource}:*`)) return true;\n\n return false;\n}\n\nexport function generateApiKey(): string {\n const chars = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n let suffix = \"\";\n for (let i = 0; i < 32; i++) {\n suffix += chars[Math.floor(Math.random() * chars.length)];\n }\n return `kyro_${suffix}`;\n}\n\nexport function generateApiKeyPrefix(key: string): string {\n return key.substring(0, 8);\n}\n","import type { User, Request } from '../hooks/types.js';\nimport { evaluateAccess, type WhereClause } from './types.js';\nimport { hasPermission } from '../auth/rbac/checker.js';\nimport { hasApiKeyPermission } from '../auth/api-key.js';\n\nexport interface AccessCheckResult {\n allowed: boolean;\n extraWhere?: WhereClause;\n error?: string;\n status?: number;\n}\n\nexport interface AccessContext {\n user?: User;\n req?: Request;\n tenantID?: string;\n apiKey?: any;\n}\n\nexport interface AccessOptions {\n enablePublicAccess?: boolean;\n defaultAccess?: string;\n}\n\nfunction actionToPermission(\n operation: \"read\" | \"create\" | \"update\" | \"delete\",\n): string {\n if (operation === \"read\") return \"read\";\n if (operation === \"create\") return \"create\";\n if (operation === \"update\") return \"update\";\n return \"delete\";\n}\n\nfunction isDefaultAllowed(\n operation: \"read\" | \"create\" | \"update\" | \"delete\",\n defaultAccess: string,\n): boolean {\n const levels: Record<string, boolean> = {\n none: false,\n read: operation === \"read\",\n create: operation === \"read\" || operation === \"create\",\n update: operation === \"read\" || operation === \"create\" || operation === \"update\",\n delete: operation === \"read\" || operation === \"create\" || operation === \"update\" || operation === \"delete\",\n admin: true,\n };\n return levels[defaultAccess] || false;\n}\n\nexport async function checkCollectionAccess(\n config: { access?: any; slug: string },\n operation: \"read\" | \"create\" | \"update\" | \"delete\",\n context: AccessContext,\n options: AccessOptions = {},\n): Promise<AccessCheckResult> {\n const { user, req, tenantID, apiKey } = context;\n const { enablePublicAccess = true, defaultAccess = \"none\" } = options;\n const accessRule = config.access?.[operation];\n\n // Custom access function (highest priority)\n if (accessRule) {\n const allowed = await evaluateAccess(accessRule, {\n req: req!,\n user,\n tenantID,\n });\n if (allowed === false) {\n return { allowed: false, error: \"Access denied\", status: 403 };\n }\n if (typeof allowed === \"object\") {\n return { allowed: true, extraWhere: allowed as WhereClause };\n }\n return { allowed: true };\n }\n\n // API key permission check\n if (apiKey?.permissions?.length > 0) {\n const resource = config.slug;\n const action = actionToPermission(operation);\n const permission = `${resource}:${action}`;\n if (\n !hasApiKeyPermission(apiKey.permissions, permission) &&\n !hasApiKeyPermission(apiKey.permissions, `${resource}:admin`)\n ) {\n return { allowed: false, error: \"Access denied: insufficient permissions\", status: 403 };\n }\n return { allowed: true };\n }\n\n // No accessRule, no apiKey — authenticated user RBAC\n if (user) {\n const resource = config.slug;\n const action = actionToPermission(operation);\n const permission = `${resource}:${action}`;\n\n const userHas = hasPermission(\n { id: user.id, email: user.email, role: user.role } as any,\n permission,\n );\n const adminHas = hasPermission(\n { id: user.id, email: user.email, role: user.role } as any,\n `${resource}:admin`,\n );\n\n if (userHas || adminHas) {\n return { allowed: true };\n }\n return { allowed: false, error: \"Access denied: missing RBAC permission\", status: 403 };\n }\n\n // Unauthenticated — check public access\n const defaultAllowed = isDefaultAllowed(operation, defaultAccess);\n if (enablePublicAccess && defaultAllowed) {\n return { allowed: true };\n }\n\n return { allowed: false, error: \"Authentication required\", status: 401 };\n}\n\nexport async function checkGlobalAccess(\n config: { access?: any; slug: string },\n operation: \"read\" | \"update\",\n context: AccessContext,\n options: AccessOptions = {},\n): Promise<AccessCheckResult> {\n const { user, req, tenantID } = context;\n const { enablePublicAccess = true } = options;\n const accessRule = config.access?.[operation];\n\n // Custom access function\n if (accessRule) {\n const allowed = await evaluateAccess(accessRule, {\n req: req!,\n user,\n tenantID,\n });\n if (allowed === false) {\n return { allowed: false, error: \"Access denied\", status: 403 };\n }\n return { allowed: true };\n }\n\n // Authenticated user RBAC\n if (user) {\n const permission = `globals:${operation}`;\n const userHas = hasPermission(\n { id: user.id, email: user.email, role: user.role } as any,\n permission,\n );\n const adminHas = hasPermission(\n { id: user.id, email: user.email, role: user.role } as any,\n \"globals:admin\",\n );\n if (userHas || adminHas) {\n return { allowed: true };\n }\n return { allowed: false, error: \"Access denied: missing RBAC permission\", status: 403 };\n }\n\n // Unauthenticated\n if (enablePublicAccess) {\n return { allowed: true };\n }\n\n return { allowed: false, error: \"Authentication required\", status: 401 };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkE2763JUP_cjs = require('./chunk-E2763JUP.cjs');
3
+ var chunkDRVOUQMT_cjs = require('./chunk-DRVOUQMT.cjs');
4
4
  var chunk5PMQQFRE_cjs = require('./chunk-5PMQQFRE.cjs');
5
5
  var chunkIDVRRRAK_cjs = require('./chunk-IDVRRRAK.cjs');
6
6
  var chunkRFFSZSCL_cjs = require('./chunk-RFFSZSCL.cjs');
@@ -19,7 +19,7 @@ async function doInit() {
19
19
  if (exports.kyroInstance) return;
20
20
  try {
21
21
  const config = projectConfig__default.default.default || projectConfig__default.default;
22
- exports.kyroInstance = chunkE2763JUP_cjs.createKyro(config);
22
+ exports.kyroInstance = chunkDRVOUQMT_cjs.createKyro(config);
23
23
  await exports.kyroInstance.init();
24
24
  await exports.kyroInstance.loadSettings();
25
25
  const db = exports.kyroInstance.db;
@@ -31,7 +31,7 @@ async function doInit() {
31
31
  const authDbPath = process.env.KYRO_AUTH_DB_PATH || "./data/auth.db";
32
32
  bootstrapAuthAdapter = new chunkIDVRRRAK_cjs.SQLiteAuthAdapter({ path: authDbPath });
33
33
  }
34
- } else if (db instanceof chunkE2763JUP_cjs.LocalAdapter) {
34
+ } else if (db instanceof chunkDRVOUQMT_cjs.LocalAdapter) {
35
35
  const authDbPath = process.env.KYRO_AUTH_DB_PATH || "./data/auth.db";
36
36
  bootstrapAuthAdapter = new chunkIDVRRRAK_cjs.SQLiteAuthAdapter({ path: authDbPath });
37
37
  } else if (db instanceof chunkQ23GAMLE_cjs.MongoDBAdapter) {
@@ -95,5 +95,5 @@ var ALL = async (context) => {
95
95
 
96
96
  exports.ALL = ALL;
97
97
  exports.warmKyroInstance = warmKyroInstance;
98
- //# sourceMappingURL=chunk-NWUEVLQT.cjs.map
99
- //# sourceMappingURL=chunk-NWUEVLQT.cjs.map
98
+ //# sourceMappingURL=chunk-OZ3CCTTA.cjs.map
99
+ //# sourceMappingURL=chunk-OZ3CCTTA.cjs.map