arckode-framework 1.4.1 → 1.4.2

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.
@@ -159,6 +159,7 @@ export async function checkConnectorLogic(
159
159
  for (const connFile of connectors) {
160
160
  try {
161
161
  const content = await readFile(join(connectorsPath, connFile), 'utf-8')
162
+ if (content.includes('@ignore CONNECTOR_BUSINESS_LOGIC')) continue
162
163
  let businessHits = 0
163
164
  for (const pattern of businessPatterns) {
164
165
  const matches = content.match(pattern)
@@ -287,6 +288,13 @@ export async function checkModuleQuality(
287
288
  } catch { /* no subdir */ }
288
289
  }
289
290
 
291
+ // Patrones que indican verificación de ownership (en ventana antes o después de findById)
292
+ const ownershipPatterns = [
293
+ 'assertOwnership', 'assertPerteneceAlLocal', 'userId', 'ownerId',
294
+ 'authUserId', 'currentUser', 'ForbiddenError', 'No es tu', 'No tenés',
295
+ 'No pertenece', 'acceso a este',
296
+ ]
297
+
290
298
  for (const filePath of filesToScan) {
291
299
  if (/-orm\.ts$|-repo\.ts$|-repository\.ts$|repository\.ts$/.test(filePath)) continue
292
300
  try {
@@ -300,10 +308,19 @@ export async function checkModuleQuality(
300
308
  const closes = (line.match(/\}/g) ?? []).length
301
309
  if (insideInterface > 0) insideInterface = Math.max(0, insideInterface + opens - closes)
302
310
  if (insideInterface > 0) continue
303
- if (/^\s*findById\s*\([^)]*\)\s*:/.test(line)) continue
311
+ if (/^\s*(async\s+)?findById\s*\([^)]*\)\s*:/.test(line)) continue
304
312
  if (/\bfindById\s*\(/.test(line)) {
305
- const window = fileLines.slice(i + 1, i + 6).join('\n')
306
- if (!window.includes('assertOwnership') && !window.includes('userId') && !window.includes('ownerId')) {
313
+ // @ignore IDOR_RISK suppress false positives
314
+ if (line.includes('@ignore IDOR_RISK') || (i > 0 && fileLines[i - 1]?.includes('@ignore IDOR_RISK'))) continue
315
+
316
+ // Check 10 lines AFTER findById
317
+ const afterWindow = fileLines.slice(i + 1, i + 11).join('\n')
318
+ // Check 5 lines BEFORE findById (for pre-validation patterns like authContext checks)
319
+ const beforeWindow = fileLines.slice(Math.max(0, i - 5), i).join('\n')
320
+ const combinedWindow = beforeWindow + '\n' + afterWindow
321
+
322
+ const hasOwnership = ownershipPatterns.some(p => combinedWindow.includes(p))
323
+ if (!hasOwnership) {
307
324
  violations.push({ type: 'IDOR_RISK', module: module.name, message: `"${relative(modulesPath, filePath)}" línea ${i + 1}: findById sin verificación de ownership. Usar auth.assertOwnership() para prevenir IDOR.` })
308
325
  break
309
326
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arckode-framework",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "description": "AI-first TypeScript/Bun framework. Modular, SOLID, zero magic. The AI reads the composition root and knows everything.",
5
5
  "type": "module",
6
6
  "main": "./kernel/framework.ts",