sparda-mcp 0.66.2 → 0.68.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 +28 -3
- package/package.json +6 -5
- package/src/commands/claude-hook.js +105 -0
- package/src/commands/gate.js +28 -2
- package/src/commands/prove.js +12 -1
- package/src/commands/remove.js +3 -0
- package/src/detect.js +34 -0
- package/src/index.js +24 -2
- package/src/server/stdio.js +1 -1
- package/src/ubg/apocalypse.js +100 -15
- package/src/ubg/compile.js +2 -0
- package/src/ubg/express.js +43 -1
- package/src/ubg/extract.js +810 -27
- package/src/ubg/nestjs.js +262 -11
- package/src/ubg/prisma.js +18 -8
- package/src/ubg/resolve.js +73 -7
- package/src/ubg/strapi.js +510 -0
- package/src/ubg/translate.js +3 -0
package/src/ubg/express.js
CHANGED
|
@@ -6,11 +6,24 @@
|
|
|
6
6
|
// Depth stays bounded like the v0 parser: entry file + mounted routers.
|
|
7
7
|
import fs from 'node:fs';
|
|
8
8
|
import path from 'node:path';
|
|
9
|
-
import { parseModule, resolveRelImport } from './extract.js';
|
|
9
|
+
import { parseModule, resolveRelImport, authDenyCall } from './extract.js';
|
|
10
10
|
import { createResolver, relOf } from './resolve.js';
|
|
11
11
|
|
|
12
12
|
const HTTP = new Set(['get', 'post', 'put', 'patch', 'delete']);
|
|
13
13
|
|
|
14
|
+
// A minimal scan carrying ONLY the deny signal — attached to a middleware recognized as a known
|
|
15
|
+
// auth-library guard (ADR-069: `passport.authenticate()`, `expressjwt({…})`) whose body lives in
|
|
16
|
+
// node_modules and so can't be read in-repo. The catalog is a VERIFIED published fact, so the guard
|
|
17
|
+
// earns `verified` (→ can reach PROVEN), not merely `asserted`. No effects/reads enter the graph.
|
|
18
|
+
const AUTH_DENY_SCAN = {
|
|
19
|
+
effects: [],
|
|
20
|
+
returnShapes: [],
|
|
21
|
+
calls: [],
|
|
22
|
+
async: false,
|
|
23
|
+
validatesInput: false,
|
|
24
|
+
guardSignals: { deniesWithStatus: true },
|
|
25
|
+
};
|
|
26
|
+
|
|
14
27
|
// → { routes, globalMiddlewares, helpers, skipped, scannedFiles }
|
|
15
28
|
export function extractExpress(cwd, entryFile) {
|
|
16
29
|
const routes = [];
|
|
@@ -224,6 +237,10 @@ export function extractExpress(cwd, entryFile) {
|
|
|
224
237
|
sourceFile: relFile,
|
|
225
238
|
sourceLine: arg.loc?.start.line ?? 0,
|
|
226
239
|
fn: arg,
|
|
240
|
+
// deep-scan the inline handler like every other callable branch: follows its
|
|
241
|
+
// service/model calls AND carries the module's effect-client provenance (import
|
|
242
|
+
// labels), so an SDK call in an inline handler is recognized by origin.
|
|
243
|
+
scan: resolver.deepScan(arg, mod),
|
|
227
244
|
};
|
|
228
245
|
}
|
|
229
246
|
if (arg.type === 'CallExpression') {
|
|
@@ -247,6 +264,20 @@ export function extractExpress(cwd, entryFile) {
|
|
|
247
264
|
scan: resolver.deepScan(fnArg, mod),
|
|
248
265
|
};
|
|
249
266
|
}
|
|
267
|
+
// known auth-library deny-form middleware (ADR-069): `passport.authenticate('jwt')`,
|
|
268
|
+
// `expressjwt({…})`. Its body is in node_modules (opaque), but the catalog is a verified
|
|
269
|
+
// published fact that it denies — so the guard reads VERIFIED, not asserted, and its app
|
|
270
|
+
// can legitimately reach PROVEN. Deny-FORM precision (a custom callback / credentialsRequired
|
|
271
|
+
// false) is handled in authDenyCall, which abstains rather than over-verify.
|
|
272
|
+
if (authDenyCall(arg, mod.authGuards?.pkgOf)) {
|
|
273
|
+
return {
|
|
274
|
+
name,
|
|
275
|
+
sourceFile: relFile,
|
|
276
|
+
sourceLine: arg.loc?.start.line ?? 0,
|
|
277
|
+
fn: null,
|
|
278
|
+
scan: AUTH_DENY_SCAN,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
250
281
|
// factory middleware: validate(schema), rateLimit({…}) — the factory
|
|
251
282
|
// name is known, the produced closure is out of static reach (blind node)
|
|
252
283
|
return {
|
|
@@ -329,6 +360,17 @@ export function extractExpress(cwd, entryFile) {
|
|
|
329
360
|
};
|
|
330
361
|
}
|
|
331
362
|
}
|
|
363
|
+
// aliased auth-library guard (ADR-069): `const requireAuth = passport.authenticate('jwt')`
|
|
364
|
+
// used by name here — verified by the catalog, exactly like the inline form above.
|
|
365
|
+
if (mod.authGuards?.denyBindings?.has(arg.name)) {
|
|
366
|
+
return {
|
|
367
|
+
name: arg.name,
|
|
368
|
+
sourceFile: relFile,
|
|
369
|
+
sourceLine: arg.loc?.start.line ?? 0,
|
|
370
|
+
fn: null,
|
|
371
|
+
scan: AUTH_DENY_SCAN,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
332
374
|
// known but bodyless — node exists, microscope stays blind
|
|
333
375
|
return {
|
|
334
376
|
name: arg.name,
|