@voltro/cli 0.54.0 → 0.56.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/CHANGELOG.md +639 -2
- package/bin/voltro.mjs +24 -0
- package/dist/{apiBuild-DTWp0S_q.js → apiBuild-Bdaetr37.js} +119 -88
- package/dist/apiBuild-Vw1figjO.js +2 -0
- package/dist/bin.js +1 -1
- package/dist/{build-D4ygSbnV.js → build-CI36wL4R.js} +339 -314
- package/dist/buildReport-52gHKgfO.js +64 -0
- package/dist/{checkCommand-Dg1G7Gwd.js → checkCommand-CAwFXrxA.js} +6 -6
- package/dist/{checkCommand-L7DTlpIF.js → checkCommand-D0QV_zM_.js} +1 -1
- package/dist/{clusterCmd-DrVFCzSj.js → clusterCmd-CdLB1GkT.js} +1 -1
- package/dist/{codegen-DSLM8Su9.js → codegen-Bth5lUTU.js} +76 -64
- package/dist/codegen-DbH7NbCR.js +2 -0
- package/dist/{codegenCommand-CG_Vx4lc.js → codegenCommand-CidbQzbv.js} +15 -14
- package/dist/{codemodRunner-Cd4xkC6u.js → codemodRunner-BlQPfjzA.js} +277 -0
- package/dist/{commands-6Kzi92Np.js → commands-CWjfThXv.js} +35 -35
- package/dist/{dashboardCommand-Cq1PWvI1.js → dashboardCommand-BekcY5Ls.js} +3 -3
- package/dist/{dataCommand-DYzW8vkv.js → dataCommand-2pccgbIy.js} +267 -195
- package/dist/{dbCommand-B4NWZtGL.js → dbCommand-DpK_vQET.js} +457 -441
- package/dist/dbCommand-DrycGWWt.js +2 -0
- package/dist/{dev-cKUiZZsB.js → dev-B9Gz0k85.js} +1 -1
- package/dist/{dev-CmuvUKRq.js → dev-Dw263KPu.js} +2598 -2452
- package/dist/doctorCommand-BMWs6aVm.js +2 -0
- package/dist/{doctorCommand-DCiFVMtZ.js → doctorCommand-aR_bFmIi.js} +353 -251
- package/dist/{dormancyCommand-w1TrmgYP.js → dormancyCommand-eXTQMbHU.js} +1 -1
- package/dist/{embeddingsCommand-CMgPyRTr.js → embeddingsCommand-CTmiQvwa.js} +1 -1
- package/dist/{envCommand-Cyynmcfa.js → envCommand-BDUgV7EM.js} +12 -12
- package/dist/{evolveCommand-BwvQ8dVH.js → evolveCommand-YV8qW1LU.js} +2 -2
- package/dist/frameworkTableAssembly-CGNC0qr7.js +2 -0
- package/dist/{frameworkTableAssembly-D7LJuALW.js → frameworkTableAssembly-DNOFXfEQ.js} +102 -100
- package/dist/index.js +1 -1
- package/dist/{infoCommand-DlYlUPqs.js → infoCommand-BjVXpMlP.js} +1 -1
- package/dist/inspect-CNYvNXPU.js +1484 -0
- package/dist/inspect-S2rWy1Ys.js +2 -0
- package/dist/{inspectCmd-niF97fAq.js → inspectCmd-CP-G0sVK.js} +1 -1
- package/dist/{inspectFetch-EMuhTG_9.js → inspectFetch-BU1NyzxV.js} +36 -24
- package/dist/{inspectMetrics-CGF94puw.js → inspectMetrics-BY0Sjb2F.js} +19 -19
- package/dist/interruptedReplace-CwnkBb2X.js +41 -0
- package/dist/interruptedReplace-qzmFI020.js +2 -0
- package/dist/{logsCmd-B6oNsfaZ.js → logsCmd-BU8uCdys.js} +1 -1
- package/dist/{manifestBuild-Cqgsx2bM.js → manifestBuild-CEkjfpwc.js} +1 -1
- package/dist/manifestBuild-DIa_s6u0.js +2 -0
- package/dist/{migrate-BK_Bbx-_.js → migrate-SICulyz1.js} +2 -2
- package/dist/precompressAssets-YhTi1aWp.js +40 -0
- package/dist/{probeCommand-_C0YU207.js → probeCommand-6HxEkNDG.js} +2 -2
- package/dist/{runtimeTrace-CGWx1Q6l.js → runtimeTrace-DgYMc09E.js} +1 -1
- package/dist/{scheduleCmd-DQRu6BZC.js → scheduleCmd-DYBUfo_T.js} +1 -1
- package/dist/{sdkgen-CDGHQUFj.js → sdkgen-PY-umd6O.js} +1 -1
- package/dist/{seedRunner-Dgsiwk_e.js → seedRunner-DISBKow-.js} +16 -16
- package/dist/serveCommand-BITS8Hpj.js +2 -0
- package/dist/{serveCommand-Bje09q1v.js → serveCommand-DIJ3ma76.js} +951 -909
- package/dist/serveEntry.js +1 -1
- package/dist/{start-Clz-1BHB.js → start-B9NGB8gn.js} +627 -588
- package/dist/{start-B0bnJgxI.js → start-BFQQkL1i.js} +1 -1
- package/dist/startEntry.js +1 -1
- package/dist/staticCachePolicy-CIyj6DbS.js +15 -0
- package/dist/{test-D_kW4KMj.js → test-jipIQ5Mx.js} +1 -1
- package/dist/{tracesCmd-DgtgOUdi.js → tracesCmd-BWYDqMy6.js} +1 -1
- package/dist/{updateCommand-CRJlAOaM.js → updateCommand-C9n_Z_oG.js} +8 -2
- package/dist/updateCommand-DsXEAHbd.js +2 -0
- package/dist/webDev-C2dRz9s5.js +2 -0
- package/dist/{webDev-DSI9SOhs.js → webDev-C53hJdcL.js} +1265 -1288
- package/dist/{webhooksCommand-BvzXNHji.js → webhooksCommand-uuPu8qQX.js} +1 -1
- package/dist/{workflowsCmd-BGF-mRZ5.js → workflowsCmd-g-DNpaUc.js} +1 -1
- package/package.json +67 -19
- package/templates/AGENTS.core.md +20 -1
- package/templates/AGENTS.md +21 -2
- package/templates/agent-docs/_index.md +1 -1
- package/templates/agent-docs/_manifest.json +1 -1
- package/templates/agent-docs/authentication.md +49 -6
- package/templates/agent-docs/cli.md +216 -11
- package/templates/agent-docs/data.md +209 -18
- package/templates/agent-docs/database/scaling.md +40 -1
- package/templates/agent-docs/deployment.md +53 -1
- package/templates/agent-docs/internationalization.md +32 -0
- package/templates/agent-docs/local-first-mobile.md +9 -2
- package/templates/agent-docs/observability.md +227 -0
- package/templates/agent-docs/plugins/billing.md +15 -0
- package/templates/agent-docs/plugins/broadcast.md +2 -1
- package/templates/agent-docs/plugins/ratelimit.md +6 -1
- package/templates/agent-docs/plugins/row-history.md +11 -0
- package/templates/agent-docs/plugins.md +65 -8
- package/templates/agent-docs/reference.md +5 -3
- package/templates/agent-docs/routing.md +18 -0
- package/templates/agent-docs/schema-driven-ui.md +125 -0
- package/templates/agent-docs/templates/appshells.md +3 -3
- package/templates/agent-docs/whats-new.md +408 -106
- package/templates/apps/api-ai/package.json +6 -6
- package/templates/apps/api-auth/package.json +8 -8
- package/templates/apps/api-backend/package.json +7 -7
- package/templates/apps/api-backend-deactivation/package.json +7 -7
- package/templates/apps/api-backend-mail/package.json +8 -8
- package/templates/apps/api-backend-mariadb/package.json +9 -9
- package/templates/apps/api-backend-sqlite/package.json +8 -8
- package/templates/apps/api-backend-storage/package.json +8 -8
- package/templates/apps/api-cms/package.json +9 -9
- package/templates/apps/api-collab/package.json +8 -8
- package/templates/apps/api-data-advanced/package.json +8 -8
- package/templates/apps/api-durable/package.json +8 -8
- package/templates/apps/api-feature-flags/package.json +9 -9
- package/templates/apps/api-governance/package.json +8 -8
- package/templates/apps/api-kv/package.json +8 -8
- package/templates/apps/api-moderation/package.json +8 -8
- package/templates/apps/api-observability/package.json +8 -8
- package/templates/apps/api-ratelimit/package.json +8 -8
- package/templates/apps/api-rbac/package.json +8 -8
- package/templates/apps/api-rest/package.json +7 -7
- package/templates/apps/api-row-history/package.json +8 -8
- package/templates/apps/api-saas/package.json +11 -11
- package/templates/apps/api-saas-starter/package.json +10 -10
- package/templates/apps/api-search/package.json +8 -8
- package/templates/apps/api-status/package.json +8 -8
- package/templates/apps/api-webhooks/package.json +9 -9
- package/templates/apps/changelog/package.json +7 -7
- package/templates/apps/changelog/src/pages/[locale]/page.tsx +7 -1
- package/templates/apps/edge-functions/package.json +2 -2
- package/templates/apps/frontend-admin/package.json +7 -8
- package/templates/apps/frontend-admin/src/pages/(marketing)/layout.tsx +1 -2
- package/templates/apps/frontend-admin/src/pages/admin/layout.tsx +1 -2
- package/templates/apps/frontend-app/package.json +8 -9
- package/templates/apps/frontend-app/src/pages/layout.tsx +1 -2
- package/templates/apps/frontend-auth/package.json +7 -8
- package/templates/apps/frontend-auth/src/components/AuthShell.tsx +1 -2
- package/templates/apps/frontend-blank/package.json +6 -7
- package/templates/apps/frontend-blank/src/pages/layout.tsx +1 -2
- package/templates/apps/frontend-cms/package.json +8 -9
- package/templates/apps/frontend-cms/src/pages/(app)/layout.tsx +1 -2
- package/templates/apps/frontend-collab/README.md +7 -2
- package/templates/apps/frontend-collab/package.json +9 -10
- package/templates/apps/frontend-collab/src/pages/layout.tsx +1 -2
- package/templates/apps/frontend-collab/src/pages/page.test.tsx +8 -4
- package/templates/apps/frontend-collab/src/pages/page.tsx +10 -5
- package/templates/apps/frontend-contact/package.json +7 -7
- package/templates/apps/frontend-contact/src/components/ContactForm.island.tsx +1 -1
- package/templates/apps/frontend-dashboard/package.json +6 -7
- package/templates/apps/frontend-dashboard/src/pages/(marketing)/layout.tsx +1 -2
- package/templates/apps/frontend-dashboard/src/pages/dashboard/layout.tsx +1 -2
- package/templates/apps/frontend-docs/package.json +8 -8
- package/templates/apps/frontend-i18n/package.json +6 -6
- package/templates/apps/frontend-landing/package.json +7 -7
- package/templates/apps/frontend-portal/package.json +7 -8
- package/templates/apps/frontend-portal/src/pages/(portal)/layout.tsx +1 -2
- package/templates/apps/frontend-saas/package.json +7 -8
- package/templates/apps/frontend-saas/src/pages/(marketing)/layout.tsx +1 -2
- package/templates/apps/frontend-saas/src/pages/dashboard/layout.tsx +1 -2
- package/templates/apps/frontend-spa/package.json +6 -7
- package/templates/apps/frontend-spa/src/pages/layout.tsx +1 -2
- package/templates/apps/frontend-ssr/package.json +6 -7
- package/templates/apps/frontend-ssr/src/pages/layout.tsx +1 -2
- package/templates/apps/frontend-ssr-api/package.json +7 -8
- package/templates/apps/frontend-ssr-api/src/pages/layout.tsx +1 -2
- package/templates/apps/frontend-static-blog/package.json +8 -8
- package/templates/apps/frontend-static-blog/src/components/ReadingProgress.island.tsx +1 -1
- package/templates/apps/frontend-static-blog/src/pages/[locale]/page.tsx +7 -1
- package/templates/apps/frontend-status/package.json +7 -8
- package/templates/apps/frontend-status/src/pages/layout.tsx +1 -2
- package/templates/apps/mobile-app/package.json +4 -4
- package/templates/baselines/compose/docker/api.Dockerfile +61 -5
- package/templates/baselines/compose/docker/web.Dockerfile +55 -10
- package/templates/baselines/compose-mariadb/docker/api.Dockerfile +61 -5
- package/templates/baselines/compose-mariadb/docker/web.Dockerfile +55 -10
- package/dist/apiBuild-CeUN55uk.js +0 -2
- package/dist/codegen-DjgxEOnD.js +0 -2
- package/dist/dbCommand-CSFWs9ev.js +0 -2
- package/dist/doctorCommand-J3qu4E0Y.js +0 -2
- package/dist/frameworkTableAssembly-IPD1pUnZ.js +0 -2
- package/dist/inspect-Bd8-9wsi.js +0 -1193
- package/dist/inspect-CuoDInfZ.js +0 -2
- package/dist/interruptedReplace-C3O3M1MM.js +0 -28
- package/dist/interruptedReplace-CvmiAM9K.js +0 -2
- package/dist/manifestBuild-C4-J1-m_.js +0 -2
- package/dist/serveCommand-BiPe8BJm.js +0 -2
- package/dist/updateCommand-CIoVDKnj.js +0 -2
- package/dist/webDev-DlvZO30c.js +0 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Ht as e, Ut as t, Wt as n } from "./dev-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { Ht as e, Ut as t, Wt as n } from "./dev-Dw263KPu.js";
|
|
2
|
+
import { F as r, Ft as i, Mt as a, Nt as o, Pt as s, S as c, t as l, u } from "./webDev-C53hJdcL.js";
|
|
3
|
+
import { r as d, u as f } from "./apiBuild-Bdaetr37.js";
|
|
4
|
+
import { x as p } from "./frameworkTableAssembly-DNOFXfEQ.js";
|
|
5
|
+
import { n as m } from "./pageConvention-CMpfDN6r.js";
|
|
6
6
|
import { n as h, r as g, t as ee } from "./cliOutput-D1tSBoRM.js";
|
|
7
7
|
import { n as _, t as te } from "./tsconfigPaths-BWXBWgcl.js";
|
|
8
8
|
import { n as ne, r as re } from "./fileTaxonomy-CbyMQYx_.js";
|
|
@@ -367,15 +367,15 @@ var le = /* @__PURE__ */ new Set([
|
|
|
367
367
|
" reaches your deploy target is not knowable from here — a secret manager",
|
|
368
368
|
" or a CI variable is not a file. Naming it nowhere is conclusive; naming",
|
|
369
369
|
" it somewhere is not a guarantee."
|
|
370
|
-
].join("\n"),
|
|
370
|
+
].join("\n"), Pe = {
|
|
371
371
|
"@voltro/cli": "provides the `voltro` binary; consumed by scripts, never imported",
|
|
372
372
|
"@voltro/devtools": "mounted by `voltro dev` itself",
|
|
373
373
|
"@voltro/sql-postgres": "dialect driver, loaded by the framework from config",
|
|
374
374
|
"@voltro/sql-mysql": "dialect driver, loaded by the framework from config",
|
|
375
375
|
"@voltro/sql-sqlite": "dialect driver, loaded by the framework from config",
|
|
376
376
|
"@voltro/sql-mssql": "dialect driver, loaded by the framework from config"
|
|
377
|
-
},
|
|
378
|
-
if (n > 12 ||
|
|
377
|
+
}, Fe = /* @__PURE__ */ new Set(["@voltro/client", "@voltro/web"]), Ie = /(^|\/)(node_modules|dist|build|\.framework|\.next|\.turbo|\.git|coverage|\.publish)(\/|$)/, Le = /\.([cm]?[jt]sx?)$/, Re = /\.generated\.[cm]?[jt]sx?$/, ze = (e, t = [], n = 0) => {
|
|
378
|
+
if (n > 12 || Ie.test(e)) return t;
|
|
379
379
|
let r;
|
|
380
380
|
try {
|
|
381
381
|
r = w(e);
|
|
@@ -389,10 +389,10 @@ var le = /* @__PURE__ */ new Set([
|
|
|
389
389
|
} catch {
|
|
390
390
|
continue;
|
|
391
391
|
}
|
|
392
|
-
a.isDirectory() ?
|
|
392
|
+
a.isDirectory() ? ze(r, t, n + 1) : Le.test(i) && t.push(r);
|
|
393
393
|
}
|
|
394
394
|
return t;
|
|
395
|
-
},
|
|
395
|
+
}, Be = /(?:\bfrom\s*|\bimport\s+|\bimport\s*\(\s*|\brequire\s*\(\s*)['"](@voltro\/[a-z0-9-]+)(?:\/[^'"]*)?['"]/g, Ve = (e) => e.split("\n").filter((e) => !/^\s*(\/\/|\*|\/\*)/.test(e)).join("\n"), He = (e) => {
|
|
396
396
|
let t;
|
|
397
397
|
try {
|
|
398
398
|
t = JSON.parse(C(v(e, "package.json"), "utf8"));
|
|
@@ -402,7 +402,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
402
402
|
let n = (e) => Object.keys(t[e] ?? {}).filter((e) => e.startsWith("@voltro/")).map((t) => ({
|
|
403
403
|
pkg: t,
|
|
404
404
|
declaredIn: e
|
|
405
|
-
})), r = /* @__PURE__ */ new Set(), i = [...n("dependencies"), ...n("devDependencies")].filter((e) => !r.has(e.pkg) && (r.add(e.pkg), !0)), a =
|
|
405
|
+
})), r = /* @__PURE__ */ new Set(), i = [...n("dependencies"), ...n("devDependencies")].filter((e) => !r.has(e.pkg) && (r.add(e.pkg), !0)), a = ze(e), o = a.some((e) => Re.test(e)), s = /* @__PURE__ */ new Set();
|
|
406
406
|
for (let e of a) {
|
|
407
407
|
let t;
|
|
408
408
|
try {
|
|
@@ -410,17 +410,17 @@ var le = /* @__PURE__ */ new Set([
|
|
|
410
410
|
} catch {
|
|
411
411
|
continue;
|
|
412
412
|
}
|
|
413
|
-
for (let e of
|
|
413
|
+
for (let e of Ve(t).matchAll(Be)) s.add(e[1]);
|
|
414
414
|
}
|
|
415
|
-
let c = i.filter((e) => !(e.pkg in
|
|
415
|
+
let c = i.filter((e) => !(e.pkg in Pe) && !s.has(e.pkg));
|
|
416
416
|
return {
|
|
417
417
|
declared: i.map((e) => e.pkg).sort(),
|
|
418
|
-
unimported: c.filter((e) => o || !
|
|
419
|
-
pendingCodegen: o ? [] : c.map((e) => e.pkg).filter((e) =>
|
|
420
|
-
exempt: i.map((e) => e.pkg).filter((e) => e in
|
|
418
|
+
unimported: c.filter((e) => o || !Fe.has(e.pkg)).sort((e, t) => e.pkg.localeCompare(t.pkg)),
|
|
419
|
+
pendingCodegen: o ? [] : c.map((e) => e.pkg).filter((e) => Fe.has(e)).sort(),
|
|
420
|
+
exempt: i.map((e) => e.pkg).filter((e) => e in Pe).sort(),
|
|
421
421
|
scannedFiles: a.length
|
|
422
422
|
};
|
|
423
|
-
},
|
|
423
|
+
}, Ue = (e) => {
|
|
424
424
|
if (e === null) return ["unimported deps · no package.json here — could not check"];
|
|
425
425
|
let t = `unimported deps · ${e.declared.length} @voltro/* package(s) declared, ${e.scannedFiles} file(s) scanned`;
|
|
426
426
|
if (e.declared.length === 0) return [t, " no @voltro/* dependencies declared — nothing to check"];
|
|
@@ -437,14 +437,14 @@ var le = /* @__PURE__ */ new Set([
|
|
|
437
437
|
let i = [t];
|
|
438
438
|
for (let t of e.unimported) i.push(` ⚠ ${t.pkg} — declared in ${t.declaredIn}, imported nowhere`);
|
|
439
439
|
return i.push(" a dependency nobody imports still gets installed, updated, and read as"), i.push(" evidence the package is in use — its breaking-change notes included."), i.push(" Remove it, or if it IS imported through an assembled specifier the scan"), i.push(" cannot see, keep it and ignore this line — the rule is advisory."), i.push(...r), n !== "" && i.push(` ·${n.slice(1)}`), i;
|
|
440
|
-
},
|
|
440
|
+
}, We = (e) => {
|
|
441
441
|
if (e.catalogCodes.length === 0) return;
|
|
442
442
|
let t = new Set(e.declaredLocales), n = e.catalogCodes.filter((e) => !t.has(e)).sort();
|
|
443
443
|
if (n.length !== 0) return {
|
|
444
444
|
orphaned: n,
|
|
445
445
|
noneDeclared: t.size === 0
|
|
446
446
|
};
|
|
447
|
-
},
|
|
447
|
+
}, Ge = (e, t) => {
|
|
448
448
|
let n = e.orphaned.join(", ");
|
|
449
449
|
return e.noneDeclared ? [
|
|
450
450
|
`⚠ ${t} has ${e.orphaned.length} catalog(s) — ${n} — and the app declares no \`locales:\`.`,
|
|
@@ -456,7 +456,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
456
456
|
" …or delete the files. A catalog that is never loaded looks from the inside",
|
|
457
457
|
" exactly like one that works, which is why this is worth a line."
|
|
458
458
|
] : [`⚠ ${t} has catalog(s) not in \`locales:\` — ${n} — so they are never imported.`, " Add the code(s) to `locales:` in your app config, or delete the file(s)."];
|
|
459
|
-
},
|
|
459
|
+
}, Ke = (e) => {
|
|
460
460
|
let t = e.getProperty("match");
|
|
461
461
|
if (t === void 0) return null;
|
|
462
462
|
let n = (t.asKind(O.PropertyAssignment)?.getInitializer())?.asKind(O.ObjectLiteralExpression);
|
|
@@ -493,15 +493,15 @@ var le = /* @__PURE__ */ new Set([
|
|
|
493
493
|
else return;
|
|
494
494
|
}
|
|
495
495
|
return r;
|
|
496
|
-
},
|
|
496
|
+
}, qe = (e, t) => {
|
|
497
497
|
let n = ["middleware.ts", "middleware.tsx"].find((t) => S(v(e, t)));
|
|
498
498
|
if (n === void 0) return;
|
|
499
|
-
let
|
|
499
|
+
let i = new D({
|
|
500
500
|
useInMemoryFileSystem: !0,
|
|
501
501
|
skipAddingFilesFromTsConfig: !0
|
|
502
|
-
}),
|
|
502
|
+
}), a;
|
|
503
503
|
try {
|
|
504
|
-
|
|
504
|
+
a = i.createSourceFile(n, C(v(e, n), "utf8"));
|
|
505
505
|
} catch {
|
|
506
506
|
return {
|
|
507
507
|
problems: [],
|
|
@@ -510,8 +510,8 @@ var le = /* @__PURE__ */ new Set([
|
|
|
510
510
|
file: n
|
|
511
511
|
};
|
|
512
512
|
}
|
|
513
|
-
let
|
|
514
|
-
for (let e of
|
|
513
|
+
let o = [], s = [], c = 0;
|
|
514
|
+
for (let e of a.getVariableDeclarations()) {
|
|
515
515
|
let t = e.getInitializerIfKind(O.CallExpression);
|
|
516
516
|
if (t?.getExpression().getText() !== "defineMiddleware") continue;
|
|
517
517
|
c += 1;
|
|
@@ -520,12 +520,12 @@ var le = /* @__PURE__ */ new Set([
|
|
|
520
520
|
s.push(n);
|
|
521
521
|
continue;
|
|
522
522
|
}
|
|
523
|
-
let i =
|
|
523
|
+
let i = Ke(r);
|
|
524
524
|
if (i === void 0) {
|
|
525
525
|
s.push(n);
|
|
526
526
|
continue;
|
|
527
527
|
}
|
|
528
|
-
|
|
528
|
+
o.push({
|
|
529
529
|
exportName: n,
|
|
530
530
|
middleware: {
|
|
531
531
|
_tag: "VoltroMiddleware",
|
|
@@ -535,45 +535,45 @@ var le = /* @__PURE__ */ new Set([
|
|
|
535
535
|
});
|
|
536
536
|
}
|
|
537
537
|
return {
|
|
538
|
-
problems: o
|
|
538
|
+
problems: r(o, t).map((e) => e.message),
|
|
539
539
|
unreadable: s,
|
|
540
540
|
seen: c,
|
|
541
541
|
file: n
|
|
542
542
|
};
|
|
543
|
-
},
|
|
543
|
+
}, Je = (e) => {
|
|
544
544
|
let t = [];
|
|
545
545
|
if (e.problems.length > 0) {
|
|
546
546
|
t.push(`✗ ${e.file}: ${e.problems.length} matcher problem(s) — this REFUSES the boot`);
|
|
547
547
|
for (let n of e.problems) t.push(` • ${n}`);
|
|
548
548
|
}
|
|
549
549
|
return e.unreadable.length > 0 && t.push(`… ${e.file}: ${e.unreadable.length} matcher(s) not statically readable (${e.unreadable.join(", ")}) — doctor did NOT check them. The boot still does.`), e.seen === 0 && t.push(`… ${e.file}: no \`defineMiddleware(...)\` found — doctor checked nothing here. A middleware assigned through a variable or re-exported from another module is invisible to this rule.`), t.length === 0 && e.seen > 0 && t.push(`✓ ${e.file}: ${e.seen} middleware(s), matchers resolve and do not overlap`), t;
|
|
550
|
-
},
|
|
550
|
+
}, Ye = (e) => e.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/[^\n]*/g, "$1"), Xe = /* @__PURE__ */ new Set([
|
|
551
551
|
"requireScope",
|
|
552
552
|
"requireAnyScope",
|
|
553
553
|
"requireAuth",
|
|
554
554
|
"assertScope",
|
|
555
555
|
"assertCan",
|
|
556
556
|
"can"
|
|
557
|
-
]),
|
|
557
|
+
]), Ze = (e) => {
|
|
558
558
|
let t = /* @__PURE__ */ new Set();
|
|
559
|
-
for (let n of e) for (let e of
|
|
559
|
+
for (let n of e) for (let e of Ye(n).matchAll(/\bexport\s+(?:const|function|async\s+function)\s+((?:require|assert)[A-Z]\w*)/g)) t.add(e[1]);
|
|
560
560
|
return t;
|
|
561
|
-
},
|
|
561
|
+
}, Qe = (e, t) => {
|
|
562
562
|
for (let n of t) if (RegExp(`\\b${n}\\s*\\(`).test(e)) return n;
|
|
563
|
-
},
|
|
563
|
+
}, $e = (e) => {
|
|
564
564
|
let t = /\bsubject\s*\.\s*id\b[^\n]*?(?:!==|===|!=|==)|(?:!==|===|!=|==)[^\n]*?\bsubject\s*\.\s*id\b/.test(e), n = /(?:Error|Denied|Forbidden|Unauthorized)\b|\b(?:fail|die|throw)\b/.test(e);
|
|
565
565
|
return t && n;
|
|
566
|
-
},
|
|
566
|
+
}, et = (e, t, n) => {
|
|
567
567
|
if (e.hasDeclaredGuards) return { kind: "declared-guard" };
|
|
568
|
-
let r =
|
|
569
|
-
return i === void 0 ?
|
|
568
|
+
let r = Ye(e.src), i = Qe(r, t);
|
|
569
|
+
return i === void 0 ? $e(r) ? { kind: "inline-ownership" } : n.has(e.tag) ? { kind: "allowlisted" } : { kind: "unchecked" } : {
|
|
570
570
|
kind: "vocabulary-guard",
|
|
571
571
|
name: i
|
|
572
572
|
};
|
|
573
|
-
},
|
|
573
|
+
}, tt = (e, t, n) => {
|
|
574
574
|
let r = e.op === "delete" ? 3 : e.op === "update" ? 2 : 1;
|
|
575
575
|
return e.table !== void 0 && (t.has(e.table) && (r += 2), n.has(e.table) && e.op === "delete" && (r += 2)), r;
|
|
576
|
-
},
|
|
576
|
+
}, nt = (e, t, n) => {
|
|
577
577
|
switch (t.kind) {
|
|
578
578
|
case "declared-guard": return "guards: on the descriptor";
|
|
579
579
|
case "vocabulary-guard": return `calls ${t.name}()`;
|
|
@@ -581,15 +581,15 @@ var le = /* @__PURE__ */ new Set([
|
|
|
581
581
|
case "allowlisted": return "accepted by a previous run";
|
|
582
582
|
case "unchecked": return n ? e.op === "read" ? "no check in this file — this app registers a row filter; VERIFY it covers this table, then record it as reviewed= rather than debt" : `${e.op}s${e.table ? ` ${e.table}` : ""} with no check in this file — this app registers a row filter; VERIFY it covers this table, then record it as reviewed= rather than debt` : e.op === "read" ? "returns a row the client selected, with nothing compared to the caller" : `${e.op}s${e.table ? ` ${e.table}` : ""} with nothing constraining WHICH row`;
|
|
583
583
|
}
|
|
584
|
-
},
|
|
584
|
+
}, rt = (e) => {
|
|
585
585
|
let t = e.executors.map((t) => {
|
|
586
|
-
let n =
|
|
586
|
+
let n = et(t, e.guardVocabulary, e.allowlist);
|
|
587
587
|
return {
|
|
588
588
|
tag: t.tag,
|
|
589
589
|
path: t.path,
|
|
590
590
|
verdict: n,
|
|
591
|
-
severity:
|
|
592
|
-
why:
|
|
591
|
+
severity: tt(t, e.tenantScopedTables, e.referencedTables),
|
|
592
|
+
why: nt(t, n, e.rowFilterRegistered === !0)
|
|
593
593
|
};
|
|
594
594
|
}), n = (e) => t.filter((t) => t.verdict.kind === e).length;
|
|
595
595
|
return {
|
|
@@ -603,7 +603,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
603
603
|
},
|
|
604
604
|
unchecked: t.filter((e) => e.verdict.kind === "unchecked").sort((e, t) => t.severity - e.severity || e.tag.localeCompare(t.tag))
|
|
605
605
|
};
|
|
606
|
-
},
|
|
606
|
+
}, it = [
|
|
607
607
|
"# voltro doctor — authz allowlist",
|
|
608
608
|
"#",
|
|
609
609
|
"# Two KINDS of line, and the difference is the point:",
|
|
@@ -628,19 +628,19 @@ var le = /* @__PURE__ */ new Set([
|
|
|
628
628
|
"# `--write-authz-allowlist` PRESERVES reviewed= lines. It only ever adds debt",
|
|
629
629
|
"# lines for executors that are newly unchecked.",
|
|
630
630
|
""
|
|
631
|
-
],
|
|
631
|
+
], at = (e) => {
|
|
632
632
|
let t = [...e].map((e) => typeof e == "string" ? { tag: e } : e), n = t.filter((e) => e.reviewed === void 0).map((e) => e.tag).sort(), r = t.filter((e) => e.reviewed !== void 0).sort((e, t) => e.tag.localeCompare(t.tag));
|
|
633
633
|
return [
|
|
634
|
-
...
|
|
634
|
+
...it,
|
|
635
635
|
...n,
|
|
636
636
|
...r.length > 0 ? ["", "# reviewed — read by a human, open on purpose"] : [],
|
|
637
637
|
...r.map((e) => `${e.tag} reviewed=${e.reviewed}`),
|
|
638
638
|
""
|
|
639
639
|
].join("\n");
|
|
640
|
-
},
|
|
640
|
+
}, ot = (e, t) => {
|
|
641
641
|
let n = [...new Set(t)].sort();
|
|
642
|
-
if (e === void 0) return
|
|
643
|
-
let r =
|
|
642
|
+
if (e === void 0) return at(n.map((e) => ({ tag: e })));
|
|
643
|
+
let r = j(e).tags, i = n.filter((e) => !r.has(e));
|
|
644
644
|
return i.length === 0 ? e : [
|
|
645
645
|
e.replace(/\n+$/, ""),
|
|
646
646
|
"",
|
|
@@ -649,25 +649,25 @@ var le = /* @__PURE__ */ new Set([
|
|
|
649
649
|
...i,
|
|
650
650
|
""
|
|
651
651
|
].join("\n");
|
|
652
|
-
},
|
|
652
|
+
}, st = (e, t) => {
|
|
653
653
|
let n = [...new Set(t)];
|
|
654
654
|
if (e === void 0) return {
|
|
655
655
|
added: n.length,
|
|
656
656
|
kept: 0,
|
|
657
657
|
removed: 0
|
|
658
658
|
};
|
|
659
|
-
let r =
|
|
659
|
+
let r = j(e).tags;
|
|
660
660
|
return {
|
|
661
661
|
added: n.filter((e) => !r.has(e)).length,
|
|
662
662
|
kept: r.size,
|
|
663
663
|
removed: 0
|
|
664
664
|
};
|
|
665
|
-
},
|
|
665
|
+
}, ct = class extends Error {
|
|
666
666
|
tag;
|
|
667
667
|
constructor(e) {
|
|
668
668
|
super(`authz allowlist: '${e}' is marked reviewed with no reason. Write \`${e} reviewed=<why it is genuinely open>\`. A bare tag is the other, honest option — it records the executor as DEBT, which is what an unexplained exemption is.`), this.tag = e, this.name = "AllowlistReasonMissingError";
|
|
669
669
|
}
|
|
670
|
-
},
|
|
670
|
+
}, j = (e) => {
|
|
671
671
|
let t = [];
|
|
672
672
|
for (let n of e.split("\n")) {
|
|
673
673
|
let e = n.trim();
|
|
@@ -680,7 +680,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
680
680
|
continue;
|
|
681
681
|
}
|
|
682
682
|
let a = r[2].trim();
|
|
683
|
-
if (a.length === 0) throw new
|
|
683
|
+
if (a.length === 0) throw new ct(i);
|
|
684
684
|
t.push({
|
|
685
685
|
tag: i,
|
|
686
686
|
reviewed: a
|
|
@@ -690,13 +690,13 @@ var le = /* @__PURE__ */ new Set([
|
|
|
690
690
|
tags: new Set(t.map((e) => e.tag)),
|
|
691
691
|
entries: t
|
|
692
692
|
};
|
|
693
|
-
},
|
|
693
|
+
}, lt = (e) => {
|
|
694
694
|
let t = e.indexOf(".");
|
|
695
695
|
return t <= 0 ? void 0 : e.slice(0, t);
|
|
696
|
-
},
|
|
696
|
+
}, ut = (e, t) => {
|
|
697
697
|
let n = new Set(t.tables), r = new Set(t.rpcTags), i = /* @__PURE__ */ new Map();
|
|
698
698
|
for (let e of t.rpcTags) {
|
|
699
|
-
let t =
|
|
699
|
+
let t = lt(e);
|
|
700
700
|
if (t === void 0) continue;
|
|
701
701
|
let n = i.get(t);
|
|
702
702
|
n ? n.push(e) : i.set(t, [e]);
|
|
@@ -725,7 +725,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
725
725
|
});
|
|
726
726
|
continue;
|
|
727
727
|
}
|
|
728
|
-
let s = new Set(o.rpcTags.map(
|
|
728
|
+
let s = new Set(o.rpcTags.map(lt).filter((e) => e !== void 0));
|
|
729
729
|
for (let e of s) {
|
|
730
730
|
let t = i.get(e);
|
|
731
731
|
t !== void 0 && a.push({
|
|
@@ -738,12 +738,12 @@ var le = /* @__PURE__ */ new Set([
|
|
|
738
738
|
}
|
|
739
739
|
}
|
|
740
740
|
return a;
|
|
741
|
-
},
|
|
741
|
+
}, dt = (e, t) => {
|
|
742
742
|
let n = e.reduce((e, t) => e + t.tables.length, 0), r = [`plugin surface · ${e.length} plugin(s) contribute ${n} table(s)`];
|
|
743
743
|
if (t.length === 0) return r.push(" ✓ no overlap with your own tables or rpc namespaces"), r;
|
|
744
744
|
for (let e of t) r.push(` ${e.fatal ? "✗" : "⚠"} ${e.plugin} — ${e.detail}`), r.push(` ${e.fix}`);
|
|
745
745
|
return r;
|
|
746
|
-
},
|
|
746
|
+
}, ft = async (e) => {
|
|
747
747
|
if (!await e.hasWorkflows().catch(() => !1)) return { kind: "not-applicable" };
|
|
748
748
|
let t;
|
|
749
749
|
try {
|
|
@@ -767,12 +767,12 @@ var le = /* @__PURE__ */ new Set([
|
|
|
767
767
|
} finally {
|
|
768
768
|
await t.close().catch(() => {});
|
|
769
769
|
}
|
|
770
|
-
},
|
|
770
|
+
}, pt = (e) => {
|
|
771
771
|
let t = Math.round(e / 6e4);
|
|
772
772
|
if (t < 90) return `${t}m`;
|
|
773
773
|
let n = Math.round(t / 60);
|
|
774
774
|
return n < 48 ? `${n}h` : `${Math.round(n / 24)}d`;
|
|
775
|
-
},
|
|
775
|
+
}, mt = (e) => {
|
|
776
776
|
if (e.kind === "not-applicable") return null;
|
|
777
777
|
if (e.kind === "skipped") return `• stuck runs: NOT CHECKED — ${e.reason}\n This is the one doctor rule that reads the database rather than your source.
|
|
778
778
|
Run it where the app's DB env vars are set, or ignore this line locally.`;
|
|
@@ -780,14 +780,41 @@ var le = /* @__PURE__ */ new Set([
|
|
|
780
780
|
if (t.stalled.length === 0) n.push(`✓ stuck runs: none (${t.examined} live run(s) old enough to examine${t.waitingOnTimer > 0 ? `, ${t.waitingOnTimer} waiting on a durable timer` : ""}${t.alreadyReported > 0 ? `, ${t.alreadyReported} already reported` : ""})`);
|
|
781
781
|
else {
|
|
782
782
|
n.push(`✗ stuck runs: ${t.stalled.length} run(s) have made no progress`);
|
|
783
|
-
for (let e of t.stalled.slice(0, 20)) n.push(` ${e.tag} ${e.runId} idle ${
|
|
783
|
+
for (let e of t.stalled.slice(0, 20)) n.push(` ${e.tag} ${e.runId} idle ${pt(e.idleMs)} ${e.reason}`);
|
|
784
784
|
t.stalled.length > 20 && n.push(` … and ${t.stalled.length - 20} more`), n.push(" Nothing was changed — this is a SUSPICION, not a verdict. `awaiting-signal` usually means the sender never came.");
|
|
785
785
|
}
|
|
786
786
|
t.sawFullRunPage && n.push(" (the examined page filled up — more old runs exist than were read this pass)");
|
|
787
787
|
for (let e of t.failures) n.push(` ! could not examine ${e.subject}: ${e.detail}`);
|
|
788
788
|
return n.join("\n");
|
|
789
|
-
},
|
|
790
|
-
let t =
|
|
789
|
+
}, ht = /(?:^|\n)\s*import\s+(?!type\s)[^;'"]*?from\s+['"]@voltro\/ui-shadcn(?:\/(?!tokens\.css)[^'"]+)?['"]/, gt = /@import\s+["']@voltro\/ui-shadcn\/tokens\.css["']|@import\s+["']tailwindcss["']|from\s+['"]@voltro\/ui-shadcn\/tokens\.css['"]|import\s+['"][^'"]*@voltro\/ui-shadcn\/tokens\.css['"]/, _t = (e) => {
|
|
790
|
+
let t = [], n = [];
|
|
791
|
+
for (let r of e) gt.test(r.source) ? n.push(r.path) : !r.path.endsWith(".css") && ht.test(r.source) && t.push(r.path);
|
|
792
|
+
return {
|
|
793
|
+
kitImporters: t,
|
|
794
|
+
styleEntries: n
|
|
795
|
+
};
|
|
796
|
+
}, vt = (e) => e.kitImporters.length > 0 && e.styleEntries.length === 0, yt = (e) => {
|
|
797
|
+
if (!vt(e)) return [];
|
|
798
|
+
let t = e.kitImporters.slice(0, 5);
|
|
799
|
+
return [
|
|
800
|
+
`⚠ ui-shadcn: ${e.kitImporters.length} file(s) render kit components, and no CSS entry imports the kit's stylesheet.`,
|
|
801
|
+
...t.map((e) => ` ${e}`),
|
|
802
|
+
...e.kitImporters.length > t.length ? [` … and ${e.kitImporters.length - t.length} more`] : [],
|
|
803
|
+
"",
|
|
804
|
+
" The kit's components are Tailwind utility classes and nothing else, and",
|
|
805
|
+
" Tailwind v4 emits a utility only when a CSS entry declares it. Without",
|
|
806
|
+
" the stylesheet those classes name rules that do not exist — the markup",
|
|
807
|
+
" renders as bare browser controls. Nothing else reports this: the build",
|
|
808
|
+
" succeeds, `tsc` succeeds, and the page renders.",
|
|
809
|
+
"",
|
|
810
|
+
" Fix — add ONE line to the CSS your root layout imports:",
|
|
811
|
+
" @import \"@voltro/ui-shadcn/tokens.css\";",
|
|
812
|
+
"",
|
|
813
|
+
" Or, if this app is not a kit app, import the unstyled control instead:",
|
|
814
|
+
" import { LocaleSwitcher } from '@voltro/i18n'"
|
|
815
|
+
];
|
|
816
|
+
}, bt = (e) => S(b(e, "app.config.ts")) || S(b(e, "app.config.js")), xt = (e) => {
|
|
817
|
+
let t = f(e), n = d(e);
|
|
791
818
|
return {
|
|
792
819
|
root: e,
|
|
793
820
|
serveBundle: t,
|
|
@@ -795,22 +822,22 @@ var le = /* @__PURE__ */ new Set([
|
|
|
795
822
|
apiBundle: n,
|
|
796
823
|
apiBundlePresent: S(n)
|
|
797
824
|
};
|
|
798
|
-
},
|
|
825
|
+
}, St = [
|
|
799
826
|
"Production `voltro serve` requires a precompiled serve bundle and never transpiles on demand.",
|
|
800
827
|
"Add a `voltro build .` step BEFORE `voltro serve .` in your Dockerfile / start script.",
|
|
801
828
|
"(Generated Dockerfiles from `voltro create-project` already do this.)"
|
|
802
|
-
].join("\n "),
|
|
803
|
-
let n =
|
|
804
|
-
if (console.log(`voltro doctor — serve preflight for ${n.root}`), !
|
|
829
|
+
].join("\n "), Ct = (e, t = !1) => {
|
|
830
|
+
let n = xt(e);
|
|
831
|
+
if (console.log(`voltro doctor — serve preflight for ${n.root}`), !bt(e)) return console.log("• no app.config found here — nothing to check (run against an app root)."), 0;
|
|
805
832
|
console.log(`${n.serveBundlePresent ? "✓" : "✗"} serve bundle: ${n.serveBundlePresent ? "present" : "MISSING"} (${n.serveBundle})`), console.log(`${n.apiBundlePresent ? "✓" : "•"} api bundle: ${n.apiBundlePresent ? "present" : "absent"} (${n.apiBundle})`);
|
|
806
833
|
let r = process.env.NODE_ENV === "production";
|
|
807
834
|
if (n.serveBundlePresent) return console.log("✓ serve preflight: ready for `voltro serve`."), 0;
|
|
808
835
|
let i = t || r;
|
|
809
|
-
return console.error(`${i ? "✗" : "•"} serve bundle missing — ${i ? "production `voltro serve` will FAIL." : "a non-production `voltro serve` still runs via tsx."}`), console.error(` ${
|
|
810
|
-
},
|
|
836
|
+
return console.error(`${i ? "✗" : "•"} serve bundle missing — ${i ? "production `voltro serve` will FAIL." : "a non-production `voltro serve` still runs via tsx."}`), console.error(` ${St}`), +!!i;
|
|
837
|
+
}, wt = (e) => {
|
|
811
838
|
let t = e.absPath.replace(/\.server\.(tsx?)$/, ".$1");
|
|
812
839
|
if (t !== e.absPath) return e.sources.get(t) ?? e.sources.get(t.replace(/\.ts$/, ".tsx"));
|
|
813
|
-
},
|
|
840
|
+
}, Tt = (e, t, n) => {
|
|
814
841
|
let r = new Set(e), i = _(n), a = (e) => (/\.(tsx?|jsx?)$/.test(e) ? [e] : [
|
|
815
842
|
`${e}.ts`,
|
|
816
843
|
`${e}.tsx`,
|
|
@@ -836,7 +863,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
836
863
|
r !== void 0 && o.push(r);
|
|
837
864
|
}
|
|
838
865
|
return o;
|
|
839
|
-
}, s = /* @__PURE__ */ new Set(), c = e.filter((e) =>
|
|
866
|
+
}, s = /* @__PURE__ */ new Set(), c = e.filter((e) => Ft.test(y(n, e))), l = new Set(c);
|
|
840
867
|
for (; c.length > 0;) {
|
|
841
868
|
let e = c.shift();
|
|
842
869
|
if (!s.has(e)) {
|
|
@@ -849,11 +876,11 @@ var le = /* @__PURE__ */ new Set([
|
|
|
849
876
|
let d = /* @__PURE__ */ new Set();
|
|
850
877
|
for (let e of s) l.has(e) || u.has(e) || d.add(e);
|
|
851
878
|
return d;
|
|
852
|
-
},
|
|
879
|
+
}, M = (e) => e.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/(^|[^:])\/\/[^\n]*/g, "$1").replace(/'(?:[^'\\\n]|\\.)*'/g, "''").replace(/"(?:[^"\\\n]|\\.)*"/g, "\"\""), Et = (e, t) => (e.match(t) ?? []).length, N = (e, t) => e.getDescendantsOfKind(O.CallExpression).filter((e) => t.test(e.getExpression().getText())).length, Dt = (e, t) => {
|
|
853
880
|
if (e.src.includes(t)) return !0;
|
|
854
881
|
let n = t.replace(/^@voltro\/plugin-/, "");
|
|
855
|
-
return n !== t &&
|
|
856
|
-
},
|
|
882
|
+
return n !== t && N(e.file, RegExp(`^${n}Plugin$`)) > 0;
|
|
883
|
+
}, Ot = (e, t) => {
|
|
857
884
|
let n = [], r = RegExp(`\\b${t}\\s*(?:<[^()]*>)?\\s*\\(`, "g"), i;
|
|
858
885
|
for (; (i = r.exec(e)) !== null;) {
|
|
859
886
|
let t = i.index + i[0].length, r = 1, a = t;
|
|
@@ -861,10 +888,42 @@ var le = /* @__PURE__ */ new Set([
|
|
|
861
888
|
n.push(e.slice(t, a - 1));
|
|
862
889
|
}
|
|
863
890
|
return n;
|
|
864
|
-
},
|
|
891
|
+
}, kt = (e, t) => {
|
|
865
892
|
let n = t.getSymbol()?.getDeclarations()?.[0];
|
|
866
893
|
return n === void 0 ? [] : e.getDescendantsOfKind(O.Identifier).filter((e) => e.getSymbol()?.getDeclarations()?.[0] === n);
|
|
867
|
-
},
|
|
894
|
+
}, At = /^(insert|insertMany|insertIgnore|update|updateMany|upsert|delete|deleteMany|hardDelete|patchJson)$/, jt = /^(notify|sendNotification|sendWebhook|dispatchWebhook|sendMail|trigger[A-Z]\w*)$/, Mt = (e, t) => {
|
|
895
|
+
if (!E.isObjectLiteralExpression(e)) return;
|
|
896
|
+
let n = e.getProperty("handler");
|
|
897
|
+
if (n === void 0 || !E.isPropertyAssignment(n)) return;
|
|
898
|
+
let r = n.getInitializer();
|
|
899
|
+
if (r === void 0) return;
|
|
900
|
+
if (E.isArrowFunction(r) || E.isFunctionExpression(r)) return r;
|
|
901
|
+
if (!E.isIdentifier(r)) return;
|
|
902
|
+
let i = t.getFunction(r.getText());
|
|
903
|
+
if (i !== void 0) return i;
|
|
904
|
+
let a = t.getVariableDeclaration(r.getText())?.getInitializer();
|
|
905
|
+
if (a !== void 0 && (E.isArrowFunction(a) || E.isFunctionExpression(a))) return a;
|
|
906
|
+
}, Nt = (e) => {
|
|
907
|
+
let t = [jt], n = (E.isArrowFunction(e) || E.isFunctionExpression(e) || E.isFunctionDeclaration(e) ? e.getParameters() : [])[1];
|
|
908
|
+
if (n === void 0) return t;
|
|
909
|
+
let r = n.getNameNode();
|
|
910
|
+
if (E.isIdentifier(r)) return t.push(RegExp(`^${r.getText()}\\.publish$`)), t.push(RegExp(`^${r.getText()}\\.store\\.${At.source.replace(/^\^|\$$/g, "")}$`)), t;
|
|
911
|
+
if (E.isObjectBindingPattern(r)) for (let e of r.getElements()) {
|
|
912
|
+
let n = e.getPropertyNameNode()?.getText() ?? e.getName(), r = e.getName();
|
|
913
|
+
n === "publish" && t.push(RegExp(`^${r}$`)), n === "store" && t.push(RegExp(`^${r}\\.${At.source.replace(/^\^|\$$/g, "")}$`));
|
|
914
|
+
}
|
|
915
|
+
return t;
|
|
916
|
+
}, Pt = (e) => e.getDescendantsOfKind(O.CallExpression).filter((e) => e.getExpression().getText() === "defineSubscriber").some((t) => {
|
|
917
|
+
let n = t.getArguments()[0];
|
|
918
|
+
if (n === void 0 || !E.isObjectLiteralExpression(n) || n.getProperty("once") !== void 0) return !1;
|
|
919
|
+
let r = Mt(n, e);
|
|
920
|
+
if (r === void 0) return !1;
|
|
921
|
+
let i = Nt(r);
|
|
922
|
+
return r.getDescendantsOfKind(O.CallExpression).some((e) => {
|
|
923
|
+
let t = e.getExpression().getText();
|
|
924
|
+
return i.some((e) => e.test(t));
|
|
925
|
+
});
|
|
926
|
+
}), Ft = /\.(server|cron|workflow\.server|subscribe|reaction|outbox|startup|trigger|webhook|migration|seed)\.tsx?$/, It = /\.(query|mutation|action|stream)\.server\.tsx?$/, Lt = [
|
|
868
927
|
"Id",
|
|
869
928
|
"ID",
|
|
870
929
|
"Hash",
|
|
@@ -890,7 +949,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
890
949
|
"Comment",
|
|
891
950
|
"Provider",
|
|
892
951
|
"Format"
|
|
893
|
-
],
|
|
952
|
+
], Rt = RegExp(`(?:${Lt.join("|")})$|_(?:${Lt.map((e) => e.toLowerCase()).join("|")})$`), zt = [
|
|
894
953
|
{
|
|
895
954
|
id: "hardcoded-framework-cookie",
|
|
896
955
|
scope: "client",
|
|
@@ -903,7 +962,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
903
962
|
scope: "server",
|
|
904
963
|
smell: "an executor that never names its own descriptor — its input type is hand-written, so it can drift from the contract it implements",
|
|
905
964
|
use: "import the descriptor and type the input as `ExecutorInput<typeof descriptor>`, so the wire contract and the handler cannot disagree",
|
|
906
|
-
match: ({ src: e, path: t }) =>
|
|
965
|
+
match: ({ src: e, path: t }) => It.test(t) && !/\bimport\s[^;]*\bfrom\s*['"][^'"]*['"]/.test((e.match(/^\s*import\s[^;]*from\s*['"]\.[^'"]*['"]/gm) ?? []).join("\n"))
|
|
907
966
|
},
|
|
908
967
|
{
|
|
909
968
|
id: "subject-write-no-guard",
|
|
@@ -912,12 +971,12 @@ var le = /* @__PURE__ */ new Set([
|
|
|
912
971
|
use: "declare `guards:` on the descriptor, or — if the procedure really is open — compare the loaded row's owner against `ctx.request.subject.id` and fail with a typed error",
|
|
913
972
|
match: (e) => {
|
|
914
973
|
let { src: t, path: n } = e;
|
|
915
|
-
if (!
|
|
916
|
-
let r =
|
|
974
|
+
if (!It.test(n)) return !1;
|
|
975
|
+
let r = M(t);
|
|
917
976
|
if (!(/\bsubject\s*\.\s*id\b/.test(r) && /\b(?:insert|update|upsert|insertMany|updateMany|insertRow|upsertRow|updateManyRow)\s*\(/.test(r)) || /\b(?:guard|guards|requireScope|requireAnyScope|assertCan|assertScope|requireAuth|Unauthenticated)\b/.test(r) || /[=!]==?\s*[^;\n]*\bsubject\s*\.\s*id\b|\bsubject\s*\.\s*id\b\s*[=!]==/.test(r)) return !1;
|
|
918
|
-
let i =
|
|
977
|
+
let i = wt(e);
|
|
919
978
|
if (i === void 0) return !1;
|
|
920
|
-
let a =
|
|
979
|
+
let a = M(i);
|
|
921
980
|
return /\binternal\s*:\s*true\b/.test(a) || /\bguards\s*:\s*\[/.test(a) || /\.guard\s*\(/.test(a) ? !1 : /\bopenAccess\s*:/.test(a);
|
|
922
981
|
}
|
|
923
982
|
},
|
|
@@ -926,14 +985,14 @@ var le = /* @__PURE__ */ new Set([
|
|
|
926
985
|
scope: "server",
|
|
927
986
|
smell: "raw fetch() for outbound HTTP on the server (no traceparent, no retry, and no SSRF guard where the URL is not a constant)",
|
|
928
987
|
use: "yield* HttpClient — the framework client. It injects traceparent, retries, and honours `http.allowHosts`. Where the URL is built from anything a caller supplied it ALSO blocks loopback / RFC-1918 / link-local targets (incl. 169.254.169.254) on the initial request AND every redirect hop — for a hard-coded host that half is redundant, and the first three are still the reason to switch",
|
|
929
|
-
match: ({ file: e, path: t, serverOnly: n }) => (
|
|
988
|
+
match: ({ file: e, path: t, serverOnly: n }) => (Ft.test(t) || n) && N(e, /^(?:globalThis\.|window\.|self\.)?fetch$/) > 0
|
|
930
989
|
},
|
|
931
990
|
{
|
|
932
991
|
id: "form",
|
|
933
992
|
scope: "client",
|
|
934
993
|
smell: "per-field useState + a submit flag (hand-rolled form)",
|
|
935
994
|
use: "useFormBinding — fields + validation from the mutation input Schema; server ValidationError({ field }) routes to the field",
|
|
936
|
-
match: ({ src: e, file: t }) =>
|
|
995
|
+
match: ({ src: e, file: t }) => N(t, /^useState$/) >= 4 && /onSubmit|handleSubmit|isSubmitting/.test(e)
|
|
937
996
|
},
|
|
938
997
|
{
|
|
939
998
|
id: "table",
|
|
@@ -961,7 +1020,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
961
1020
|
scope: "client",
|
|
962
1021
|
smell: "useMemo fanning in multiple subscriptions (hand-maintained dep array)",
|
|
963
1022
|
use: "useDerived — dependency-tracked, referentially stable",
|
|
964
|
-
match: ({ src: e }) =>
|
|
1023
|
+
match: ({ src: e }) => Et(e, /\buseSubscription\s*[(<]/g) >= 3 && Et(e, /\buseMemo\s*\(/g) >= 3
|
|
965
1024
|
},
|
|
966
1025
|
{
|
|
967
1026
|
id: "next-shim",
|
|
@@ -993,7 +1052,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
993
1052
|
match: ({ file: e }) => e.getDescendantsOfKind(O.CallExpression).filter((e) => /(^|\.)useSubscription$/.test(e.getExpression().getText())).flatMap((e) => {
|
|
994
1053
|
let t = e.getFirstAncestorByKind(O.VariableDeclaration)?.getNameNode();
|
|
995
1054
|
return t === void 0 ? [] : E.isObjectBindingPattern(t) ? t.getElements().filter((e) => (e.getPropertyNameNode() ?? e.getNameNode()).getText() === "data").map((e) => e.getNameNode()) : [];
|
|
996
|
-
}).some((t) =>
|
|
1055
|
+
}).some((t) => kt(e, t).some((e) => {
|
|
997
1056
|
let t = e.getParent();
|
|
998
1057
|
if (E.isBinaryExpression(t)) {
|
|
999
1058
|
let n = t.getOperatorToken().getText(), r = t.getLeft() === e ? t.getRight() : t.getLeft();
|
|
@@ -1021,7 +1080,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1021
1080
|
scope: "server",
|
|
1022
1081
|
smell: "several sequential store reads assembling related data (an N+1 you are writing by hand)",
|
|
1023
1082
|
use: "reads are a parent→child walk on ONE key → relations() in a *.relations.ts + .with({ … }) (ONE JSON-aggregate query, every dialect); reads collect ids from SEVERAL sources → keep the assembly and run the independent leading reads under Effect.all (same queries, same results, only concurrent — zero parity risk)",
|
|
1024
|
-
match: (e) =>
|
|
1083
|
+
match: (e) => N(e.file, /\bstore\.query$/) >= 3 || N(e.file, /\bstore\.query$/) >= 2 && /\bnew Map\s*\(/.test(e.src)
|
|
1025
1084
|
},
|
|
1026
1085
|
{
|
|
1027
1086
|
id: "store-effect-lift",
|
|
@@ -1044,7 +1103,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1044
1103
|
use: ".encrypted() on the column — boot fails loudly if no cipher is configured, so it can never silently persist plaintext (a *Hash column and a vault* handle are NOT plaintext secrets: the hash IS the protection — often a unique lookup key — and the handle only names a secret held elsewhere, so both are skipped)",
|
|
1045
1104
|
match: ({ src: e }) => e.split("\n").some((e) => [...e.matchAll(/\b([A-Za-z_$][\w$]*)\s*:\s*(?:text|varchar|string|longtext)\s*\(/g)].some((t) => {
|
|
1046
1105
|
let n = t[1];
|
|
1047
|
-
return !/token|secret|credential|password|apikey|accesskey/i.test(n) ||
|
|
1106
|
+
return !/token|secret|credential|password|apikey|accesskey/i.test(n) || Rt.test(n) || /^vault/i.test(n) || /\.unique\s*\(/.test(e) ? !1 : !/\.encrypted\s*\(/.test(e);
|
|
1048
1107
|
}))
|
|
1049
1108
|
},
|
|
1050
1109
|
{
|
|
@@ -1054,15 +1113,22 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1054
1113
|
use: "you cannot look a value up by equality AND encrypt it non-deterministically — `.encrypted()` would make this column unfindable. Store the HASH as the unique lookup key and keep the secret itself either `.encrypted()` in a second column or nowhere (the framework's own `_voltro_api_keys.hashedKey` is the shape: the presented value is hashed and compared, never read back). A deterministic cipher is the other option and buys equality lookup at the cost of leaking which rows share a value",
|
|
1055
1114
|
match: ({ src: e }) => e.split("\n").some((e) => [...e.matchAll(/\b([A-Za-z_$][\w$]*)\s*:\s*(?:text|varchar|string|longtext)\s*\(/g)].some((t) => {
|
|
1056
1115
|
let n = t[1];
|
|
1057
|
-
return !/token|secret|credential|password|apikey|accesskey/i.test(n) ||
|
|
1116
|
+
return !/token|secret|credential|password|apikey|accesskey/i.test(n) || Rt.test(n) || /^vault/i.test(n) ? !1 : /\.unique\s*\(/.test(e) && !/\.encrypted\s*\(/.test(e);
|
|
1058
1117
|
}))
|
|
1059
1118
|
},
|
|
1119
|
+
{
|
|
1120
|
+
id: "subscriber-effect-without-once",
|
|
1121
|
+
scope: "server",
|
|
1122
|
+
smell: "a *.subscribe.ts handler that WRITES or publishes with no `once:` (it runs on every replica, so the effect repeats once per replica)",
|
|
1123
|
+
use: "once: true on defineSubscriber — one INSERT-wins claim per change, fleet-wide (or `once: (event) => key` for a coarser key). A hand-rolled `insertIgnore` dedupe is this, written out.",
|
|
1124
|
+
match: ({ file: e }) => Pt(e)
|
|
1125
|
+
},
|
|
1060
1126
|
{
|
|
1061
1127
|
id: "mutation-tail-effect",
|
|
1062
1128
|
scope: "server",
|
|
1063
1129
|
smell: "a notify / webhook helper called at the tail of a mutation",
|
|
1064
1130
|
use: "defineSubscriber (*.subscribe.ts) or defineReaction (*.reaction.tsx) — declarative, post-commit, with the old/new diff, instead of reactivity hidden inside every executor",
|
|
1065
|
-
match: ({ src: e, path: t }) => /\b(notify|sendNotification|sendWebhook|dispatchWebhook|trigger[A-Z]\w*)\s*\(/.test(e) && (/\bexport\s+default\b/.test(e) || /\.(mutation|action)\.server\.tsx?$/.test(t))
|
|
1131
|
+
match: ({ src: e, path: t, file: n }) => /\b(notify|sendNotification|sendWebhook|dispatchWebhook|trigger[A-Z]\w*)\s*\(/.test(e) && (/\bexport\s+default\b/.test(e) || /\.(mutation|action)\.server\.tsx?$/.test(t)) && N(n, /^(defineSubscriber|defineReaction)$/) === 0
|
|
1066
1132
|
},
|
|
1067
1133
|
{
|
|
1068
1134
|
id: "hand-cursor",
|
|
@@ -1118,9 +1184,9 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1118
1184
|
scope: "server",
|
|
1119
1185
|
smell: "setRowFilter is registered, but no test passes `rowFilter:` to makeTestContext",
|
|
1120
1186
|
use: "wire the filter into at least one test (`makeTestContext({ subject, store, rowFilter })`) and sabotage the predicate once to watch it go red — an untested row filter is a visibility rule nothing verifies",
|
|
1121
|
-
match: ({ file: e, testSources: t }) =>
|
|
1122
|
-
let t =
|
|
1123
|
-
return
|
|
1187
|
+
match: ({ file: e, testSources: t }) => N(e, /^setRowFilter$/) > 0 && ![...t.values()].some((e) => {
|
|
1188
|
+
let t = M(e);
|
|
1189
|
+
return Ot(t, "makeTestContext").length > 0 && /\browFilter\b/.test(t);
|
|
1124
1190
|
})
|
|
1125
1191
|
},
|
|
1126
1192
|
{
|
|
@@ -1130,15 +1196,15 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1130
1196
|
use: "timestampMs / timestampMsOrNull from @voltro/database/wire in the descriptor's output struct — `output` IS the serializer (it is the rpc success schema), so a Date field declared as timestampMs crosses as epoch ms on its own; declaring Schema.Number describes the WIRE type and leaves nothing to convert",
|
|
1131
1197
|
match: ({ src: e }) => /\.(getTime|toISOString)\s*\(\s*\)/.test(e) && /\.map\s*\(|=>\s*\(\{/.test(e) && /\bexport\s+default\b/.test(e)
|
|
1132
1198
|
}
|
|
1133
|
-
],
|
|
1199
|
+
], P = (e) => L(e), Bt = (e, t) => {
|
|
1134
1200
|
let n = /* @__PURE__ */ new Set();
|
|
1135
1201
|
for (let r of t) {
|
|
1136
1202
|
let t = y(e, r), i = t.split(/[\\/]/)[0];
|
|
1137
1203
|
n.add(i !== void 0 && i !== t ? i : ".");
|
|
1138
1204
|
}
|
|
1139
1205
|
return [...n].sort();
|
|
1140
|
-
},
|
|
1141
|
-
if (n > 12 ||
|
|
1206
|
+
}, F = /\.(tsx?|jsx?)$/, I = /(^|\/)(node_modules|dist|build|\.framework|\.next|coverage)(\/|$)/, Vt = /(^|[\\/])[^\\/]*\.generated\.[cm]?[jt]sx?$|\.d\.[cm]?ts$/, Ht = (e, t = [], n = 0) => {
|
|
1207
|
+
if (n > 12 || I.test(e)) return t;
|
|
1142
1208
|
let r;
|
|
1143
1209
|
try {
|
|
1144
1210
|
r = w(e, { withFileTypes: !0 });
|
|
@@ -1149,12 +1215,12 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1149
1215
|
let r = v(e, i.name);
|
|
1150
1216
|
if (i.isDirectory()) {
|
|
1151
1217
|
if (i.name.startsWith(".")) continue;
|
|
1152
|
-
|
|
1218
|
+
Ht(r, t, n + 1);
|
|
1153
1219
|
} else je.test(i.name) && t.push(r);
|
|
1154
1220
|
}
|
|
1155
1221
|
return t;
|
|
1156
|
-
},
|
|
1157
|
-
if (n > 12 ||
|
|
1222
|
+
}, L = (e, t = [], n = 0) => {
|
|
1223
|
+
if (n > 12 || I.test(e)) return t;
|
|
1158
1224
|
let r;
|
|
1159
1225
|
try {
|
|
1160
1226
|
r = w(e);
|
|
@@ -1168,11 +1234,11 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1168
1234
|
} catch {
|
|
1169
1235
|
continue;
|
|
1170
1236
|
}
|
|
1171
|
-
a.isDirectory() ?
|
|
1237
|
+
a.isDirectory() ? L(r, t, n + 1) : F.test(i) && !/\.(test|spec)\./.test(i) && !Vt.test(i) && t.push(r);
|
|
1172
1238
|
}
|
|
1173
1239
|
return t;
|
|
1174
|
-
},
|
|
1175
|
-
if (n > 12 ||
|
|
1240
|
+
}, Ut = (e, t = [], n = 0) => {
|
|
1241
|
+
if (n > 12 || I.test(e)) return t;
|
|
1176
1242
|
let r;
|
|
1177
1243
|
try {
|
|
1178
1244
|
r = w(e);
|
|
@@ -1186,17 +1252,17 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1186
1252
|
} catch {
|
|
1187
1253
|
continue;
|
|
1188
1254
|
}
|
|
1189
|
-
a.isDirectory() ?
|
|
1255
|
+
a.isDirectory() ? Ut(r, t, n + 1) : F.test(i) && /\.(test|spec)\./.test(i) && t.push(r);
|
|
1190
1256
|
}
|
|
1191
1257
|
return t;
|
|
1192
|
-
},
|
|
1193
|
-
let t =
|
|
1258
|
+
}, Wt = (e) => {
|
|
1259
|
+
let t = P(e);
|
|
1194
1260
|
return {
|
|
1195
|
-
dirs:
|
|
1261
|
+
dirs: Bt(e, t),
|
|
1196
1262
|
fileCount: t.length
|
|
1197
1263
|
};
|
|
1198
|
-
},
|
|
1199
|
-
let t =
|
|
1264
|
+
}, Gt = (e) => {
|
|
1265
|
+
let t = P(e);
|
|
1200
1266
|
if (t.length === 0) return [];
|
|
1201
1267
|
let n = new D({
|
|
1202
1268
|
useInMemoryFileSystem: !0,
|
|
@@ -1205,8 +1271,8 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1205
1271
|
for (let e of t) try {
|
|
1206
1272
|
i.set(e, C(e, "utf8"));
|
|
1207
1273
|
} catch {}
|
|
1208
|
-
let a =
|
|
1209
|
-
for (let t of
|
|
1274
|
+
let a = Tt([...i.keys()], i, e), o = /* @__PURE__ */ new Map();
|
|
1275
|
+
for (let t of Ut(e)) try {
|
|
1210
1276
|
o.set(t, C(t, "utf8"));
|
|
1211
1277
|
} catch {}
|
|
1212
1278
|
for (let s of t) {
|
|
@@ -1226,23 +1292,23 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1226
1292
|
} catch {
|
|
1227
1293
|
continue;
|
|
1228
1294
|
}
|
|
1229
|
-
for (let t of
|
|
1230
|
-
if (t.plugin !== void 0 &&
|
|
1295
|
+
for (let t of zt) {
|
|
1296
|
+
if (t.plugin !== void 0 && Dt(c, t.plugin) || !t.match(c)) continue;
|
|
1231
1297
|
let n = r.get(t.id) ?? [];
|
|
1232
1298
|
n.push(y(e, s)), r.set(t.id, n);
|
|
1233
1299
|
}
|
|
1234
1300
|
}
|
|
1235
|
-
return
|
|
1301
|
+
return zt.filter((e) => r.has(e.id)).map((e) => ({
|
|
1236
1302
|
rule: e,
|
|
1237
1303
|
files: r.get(e.id)
|
|
1238
1304
|
})).sort((e, t) => t.files.length - e.files.length || e.rule.id.localeCompare(t.rule.id));
|
|
1239
|
-
},
|
|
1240
|
-
let t =
|
|
1305
|
+
}, R = (e) => {
|
|
1306
|
+
let t = Wt(e);
|
|
1241
1307
|
return {
|
|
1242
1308
|
root: e,
|
|
1243
1309
|
scannedFiles: t.fileCount,
|
|
1244
1310
|
scannedDirs: t.dirs,
|
|
1245
|
-
findings:
|
|
1311
|
+
findings: Gt(e).map(({ rule: e, files: t }) => ({
|
|
1246
1312
|
id: e.id,
|
|
1247
1313
|
scope: e.scope,
|
|
1248
1314
|
smell: e.smell,
|
|
@@ -1250,13 +1316,13 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1250
1316
|
files: t
|
|
1251
1317
|
}))
|
|
1252
1318
|
};
|
|
1253
|
-
},
|
|
1319
|
+
}, Kt = 3, qt = .2, Jt = 50, Yt = (e, t) => e >= Jt && t > 0 && e / t >= qt, Xt = (e) => {
|
|
1254
1320
|
let t = /* @__PURE__ */ new Map();
|
|
1255
|
-
for (let n of
|
|
1321
|
+
for (let n of L(e)) try {
|
|
1256
1322
|
t.set(y(e, n), C(n, "utf8"));
|
|
1257
1323
|
} catch {}
|
|
1258
1324
|
let n = /* @__PURE__ */ new Map();
|
|
1259
|
-
for (let t of
|
|
1325
|
+
for (let t of Ht(e)) try {
|
|
1260
1326
|
n.set(y(e, t), C(t, "utf8"));
|
|
1261
1327
|
} catch {}
|
|
1262
1328
|
let r = Me({
|
|
@@ -1264,8 +1330,8 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1264
1330
|
envFiles: n
|
|
1265
1331
|
});
|
|
1266
1332
|
r !== void 0 && (console.log(""), console.log(Ne(r)));
|
|
1267
|
-
},
|
|
1268
|
-
let t =
|
|
1333
|
+
}, Zt = (e) => {
|
|
1334
|
+
let t = R(e);
|
|
1269
1335
|
if (console.log(""), t.scannedFiles === 0) return console.log(`\u2022 hand-roll scan: no source directories found under ${e}.`), console.log(" Walked the app root recursively (node_modules / dist / .framework pruned). Run `voltro doctor <app>` against an app root."), 0;
|
|
1270
1336
|
if (t.findings.length === 0) return console.log(`\u2713 hand-roll scan: ${t.scannedFiles} file${t.scannedFiles === 1 ? "" : "s"} across ${t.scannedDirs.join(", ")} \u2014 no hand-rolled primitives found.`), 0;
|
|
1271
1337
|
console.log(`\u2022 Shipped primitives you may be hand-rolling (scanned ${t.scannedFiles} files across ${t.scannedDirs.join(", ")}):`);
|
|
@@ -1276,29 +1342,29 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1276
1342
|
console.log(` [${e}]`);
|
|
1277
1343
|
let i = [...r].sort((e, t) => e.files.length - t.files.length);
|
|
1278
1344
|
for (let e of i) {
|
|
1279
|
-
if (
|
|
1345
|
+
if (Yt(e.files.length, t.scannedFiles)) {
|
|
1280
1346
|
let n = Math.round(e.files.length / t.scannedFiles * 100);
|
|
1281
1347
|
console.log(` ${e.smell} \u2014 ${e.files.length} file(s), ${n}% of those scanned: a codebase-wide pattern rather than a work list`), console.log(` \u2192 ${e.use}`), console.log(" (paths omitted on purpose at this scale — `voltro doctor --json` has every one.)");
|
|
1282
1348
|
continue;
|
|
1283
1349
|
}
|
|
1284
|
-
let r = e.files.slice(0,
|
|
1350
|
+
let r = e.files.slice(0, Kt).join(", "), i = e.files.length - Kt;
|
|
1285
1351
|
i > 0 && (n += i);
|
|
1286
1352
|
let a = i > 0 ? `, +${i} more` : "";
|
|
1287
1353
|
console.log(` ${e.smell} \u2014 ${e.files.length} file(s): ${r}${a}`), console.log(` \u2192 ${e.use}`);
|
|
1288
1354
|
}
|
|
1289
1355
|
}
|
|
1290
1356
|
return n > 0 && console.log(` (${n} more file path${n === 1 ? "" : "s"} not shown \u2014 \`voltro doctor --json\` prints every one.)`), console.log(" (See the \"Pick the SERVER primitive\" / \"Pick the CLIENT primitive\" rubrics in AGENTS.md / CLAUDE.md.)"), t.findings.length;
|
|
1291
|
-
},
|
|
1292
|
-
let t =
|
|
1357
|
+
}, Qt = "renderMode:'spa' skips this page's SSR compile while its layout shell still renders server-side — adopt it if the page BODY does not need SSR (internal/authenticated pages); keep 'ssr' if the page content needs SEO or server first-paint.", $t = /export\s+const\s+renderMode\s*(?::[^=]+)?=\s*['"]([^'"]*)['"]/, en = /export\s+const\s+dynamic\s*=\s*['"]force-(dynamic|static)['"]/, tn = (e) => {
|
|
1358
|
+
let t = $t.exec(e)?.[1];
|
|
1293
1359
|
if (t !== void 0) return t === "ssr" ? "ssr" : null;
|
|
1294
|
-
let n =
|
|
1360
|
+
let n = en.exec(e)?.[1];
|
|
1295
1361
|
return n === "dynamic" ? "ssr" : n === "static" ? null : "default";
|
|
1296
|
-
},
|
|
1362
|
+
}, z = async (e) => {
|
|
1297
1363
|
let t = v(e, "src", "pages");
|
|
1298
1364
|
if (!S(t)) return [];
|
|
1299
|
-
let { pages: n, dirs: r } = await
|
|
1365
|
+
let { pages: n, dirs: r } = await c(t), i = [];
|
|
1300
1366
|
for (let a of n) {
|
|
1301
|
-
if (!
|
|
1367
|
+
if (!u(r, a.dirChain).some((e) => e.hasLayout)) continue;
|
|
1302
1368
|
let n;
|
|
1303
1369
|
try {
|
|
1304
1370
|
n = C(v(t, a.file), "utf8");
|
|
@@ -1306,7 +1372,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1306
1372
|
continue;
|
|
1307
1373
|
}
|
|
1308
1374
|
if (l.test(n)) continue;
|
|
1309
|
-
let o =
|
|
1375
|
+
let o = tn(n);
|
|
1310
1376
|
o !== null && i.push({
|
|
1311
1377
|
file: y(e, v(t, a.file)),
|
|
1312
1378
|
pattern: a.pattern,
|
|
@@ -1314,20 +1380,20 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1314
1380
|
});
|
|
1315
1381
|
}
|
|
1316
1382
|
return i;
|
|
1317
|
-
},
|
|
1383
|
+
}, nn = 10, rn = async (e) => {
|
|
1318
1384
|
console.log("");
|
|
1319
1385
|
let t = v(e, "src", "pages");
|
|
1320
1386
|
if (!S(t)) return console.log("• spa-candidate scan: no src/pages here — nothing to check (web apps only)."), 0;
|
|
1321
|
-
let n = await
|
|
1387
|
+
let n = await z(e);
|
|
1322
1388
|
if (n.length === 0) return console.log("✓ spa-candidate scan: no loader-free, layout-backed pages to flag."), 0;
|
|
1323
1389
|
console.log(`• renderMode:'spa' candidates (${n.length} page${n.length === 1 ? "" : "s"} — loader-free, under a layout, currently ssr/default):`);
|
|
1324
|
-
for (let e of n.slice(0,
|
|
1390
|
+
for (let e of n.slice(0, nn)) {
|
|
1325
1391
|
let t = e.currentMode === "ssr" ? "renderMode:'ssr'" : "default renderMode";
|
|
1326
1392
|
console.log(` ${e.file} (${e.pattern}) — ${t}`);
|
|
1327
1393
|
}
|
|
1328
|
-
let r = n.length -
|
|
1329
|
-
return r > 0 && console.log(` (+${r} more page${r === 1 ? "" : "s"} not shown — \`voltro doctor --json\` prints every one.)`), console.log(` → ${
|
|
1330
|
-
},
|
|
1394
|
+
let r = n.length - nn;
|
|
1395
|
+
return r > 0 && console.log(` (+${r} more page${r === 1 ? "" : "s"} not shown — \`voltro doctor --json\` prints every one.)`), console.log(` → ${Qt}`), n.length;
|
|
1396
|
+
}, an = /* @__PURE__ */ new Set([
|
|
1331
1397
|
"node_modules",
|
|
1332
1398
|
"dist",
|
|
1333
1399
|
"build",
|
|
@@ -1335,7 +1401,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1335
1401
|
".vite",
|
|
1336
1402
|
".framework",
|
|
1337
1403
|
".git"
|
|
1338
|
-
]),
|
|
1404
|
+
]), on = (e, t, n) => {
|
|
1339
1405
|
let r;
|
|
1340
1406
|
try {
|
|
1341
1407
|
r = w(e, { withFileTypes: !0 });
|
|
@@ -1343,11 +1409,11 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1343
1409
|
return;
|
|
1344
1410
|
}
|
|
1345
1411
|
for (let i of r) {
|
|
1346
|
-
if (
|
|
1412
|
+
if (an.has(i.name)) continue;
|
|
1347
1413
|
let r = v(e, i.name);
|
|
1348
|
-
i.isDirectory() ?
|
|
1414
|
+
i.isDirectory() ? on(r, t, n) : i.isFile() && i.name.endsWith(".tsx") && n.push(y(t, r));
|
|
1349
1415
|
}
|
|
1350
|
-
},
|
|
1416
|
+
}, sn = (e, t) => {
|
|
1351
1417
|
let n = /* @__PURE__ */ new Set(), r = /(?:from|import)\s*\(?\s*['"](\.[^'"]*)['"]/g;
|
|
1352
1418
|
for (let i of t) {
|
|
1353
1419
|
let t;
|
|
@@ -1372,21 +1438,21 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1372
1438
|
}
|
|
1373
1439
|
}
|
|
1374
1440
|
return n;
|
|
1375
|
-
},
|
|
1441
|
+
}, cn = (e, t) => {
|
|
1376
1442
|
let n = e.slice(t.length).split(x).slice(0, -1)[0];
|
|
1377
1443
|
return n !== void 0 && n.startsWith("[");
|
|
1378
|
-
},
|
|
1444
|
+
}, B = (e) => {
|
|
1379
1445
|
let t = [], n = v(e, "src", "pages"), r = v(e, "src");
|
|
1380
1446
|
if (!S(r)) return t;
|
|
1381
1447
|
let i = [];
|
|
1382
|
-
|
|
1448
|
+
on(r, e, i), i.sort();
|
|
1383
1449
|
let a = `${y(e, n)}${x}`;
|
|
1384
|
-
|
|
1450
|
+
sn(e, i);
|
|
1385
1451
|
for (let n of i) {
|
|
1386
1452
|
let r = n.slice(n.lastIndexOf(x) + 1);
|
|
1387
1453
|
if (n.startsWith(a)) {
|
|
1388
1454
|
if (r !== "page.tsx") continue;
|
|
1389
|
-
S(v(e,
|
|
1455
|
+
S(v(e, m(n))) || t.push({
|
|
1390
1456
|
kind: "page-without-test",
|
|
1391
1457
|
file: n
|
|
1392
1458
|
});
|
|
@@ -1397,7 +1463,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1397
1463
|
file: n
|
|
1398
1464
|
});
|
|
1399
1465
|
} catch {}
|
|
1400
|
-
|
|
1466
|
+
cn(n, a) && t.push({
|
|
1401
1467
|
kind: "top-level-dynamic-route",
|
|
1402
1468
|
file: n
|
|
1403
1469
|
});
|
|
@@ -1409,32 +1475,32 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1409
1475
|
});
|
|
1410
1476
|
}
|
|
1411
1477
|
return t;
|
|
1412
|
-
},
|
|
1478
|
+
}, V = 10, H = (e, t, n) => {
|
|
1413
1479
|
if (t.length === 0) return;
|
|
1414
1480
|
console.log(`• ${e} (${t.length}):`);
|
|
1415
|
-
for (let e of t.slice(0,
|
|
1416
|
-
let r = t.length -
|
|
1481
|
+
for (let e of t.slice(0, V)) console.log(` ${e}`);
|
|
1482
|
+
let r = t.length - V;
|
|
1417
1483
|
r > 0 && console.log(` (+${r} more not shown — \`voltro doctor --json\` prints every one.)`), console.log(` → ${n}`);
|
|
1418
|
-
},
|
|
1484
|
+
}, ln = (e) => {
|
|
1419
1485
|
console.log("");
|
|
1420
1486
|
let t = v(e, "src", "pages");
|
|
1421
1487
|
if (!S(t)) return console.log("• page-convention scan: no src/pages here — nothing to check (web apps only)."), 0;
|
|
1422
|
-
let n =
|
|
1488
|
+
let n = B(e);
|
|
1423
1489
|
if (n.length === 0) return console.log("✓ page-convention scan: every route is a page.tsx in its own directory, with a test beside it."), 0;
|
|
1424
1490
|
let r = (e) => n.filter((t) => t.kind === e).map((e) => e.file);
|
|
1425
1491
|
return H("will NEVER route — page.tsx outside src/pages/", r("suffixed-outside-pages"), "the name says \"route\", the location says otherwise, and the location wins: the URL comes from the directory chain under src/pages/. Move it into the directory whose route it serves, or rename it."), H("pages with no test beside them", r("page-without-test"), "a page and its test belong together — `users/[id].page.tsx` → `users/[id].page.test.tsx`. Advisory only; a missing test is a gap, not a defect."), H("routes whose FIRST segment is dynamic — they claim every URL of that depth", r("top-level-dynamic-route"), "a route like `[id]/[code]` answers `/api/health`, `/internal/readiness` and anything else with that many segments on this origin. That is what the pattern means, so it is not a bug — but it is invisible until something requests such a URL, and then the page renders, its loader runs, and the failure reads as an application error rather than as a route claiming a path nobody meant it to. Give the route a literal first segment (`scan/[id]/[code]`) if you did not intend to own the whole origin at that depth. Advisory."), H("pages with no `meta` export — they serve the APP name as their title", r("page-without-meta"), "a page with no `meta` sets no title, so the response carries `<title>{your app.config name}</title>` — the same string on every such page, to every reader that does not run JavaScript: link previews, crawlers, a bookmark taken before hydration, a screen reader announcing the document. The client router fixes the tab after hydration, which is exactly why this is easy to miss. Add `export const meta = { title: \"…\" }` (or a function of params/loaderData). If such a page also has no real body — it redirects from an effect, say — the missing title is the symptom rather than the bug: on an `ssr` route the server answers 200 with an empty document and the redirect happens only once JavaScript runs. Move it into the loader (`redirect(...)`, a real 303). Advisory."), n.length;
|
|
1426
|
-
},
|
|
1427
|
-
let t =
|
|
1492
|
+
}, un = "voltro doctor [app] [flags]\n\nPreflight an app root: verify it can boot under production `voltro serve`,\nreport shipped primitives the source looks to be hand-rolling, and flag pages\nthat are safe `renderMode:'spa'` candidates.\n\nArguments:\n [app] App directory to check (default: the current directory).\n\nFlags:\n --strict Treat a missing serve bundle as blocking regardless of NODE_ENV\n (the `voltro serve --preflight` behavior). Without it, a missing\n bundle only fails when NODE_ENV=production.\n --json Print the complete scan as JSON — hand-roll findings AND spa\n candidates, every file path, nothing elided. Skips the preflight output.\n --write-authz-allowlist\n Record today's executors that reference NO access check into\n voltro-authz-allowlist.txt, so every later run fails only on\n ADDITIONS. The list is DEBT, not approval — an entry stops\n mattering as soon as its executor gains a guard.\n -h, --help Print this help.", dn = /* @__PURE__ */ new Map(), U = (e) => {
|
|
1493
|
+
let t = dn.get(e);
|
|
1428
1494
|
if (t !== void 0) return t;
|
|
1429
1495
|
let n = (async () => {
|
|
1430
|
-
let { walk: t, loadDiscovered: n } = await import("./dev-
|
|
1496
|
+
let { walk: t, loadDiscovered: n } = await import("./dev-B9Gz0k85.js"), r = await t(e);
|
|
1431
1497
|
return {
|
|
1432
1498
|
files: r,
|
|
1433
1499
|
discovered: await n(r)
|
|
1434
1500
|
};
|
|
1435
1501
|
})();
|
|
1436
|
-
return
|
|
1437
|
-
},
|
|
1502
|
+
return dn.set(e, n), n;
|
|
1503
|
+
}, fn = async (e) => {
|
|
1438
1504
|
let t;
|
|
1439
1505
|
try {
|
|
1440
1506
|
let { files: n, discovered: r } = await U(e), i = r.tables.map((e) => {
|
|
@@ -1450,7 +1516,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1450
1516
|
return;
|
|
1451
1517
|
}
|
|
1452
1518
|
t !== null && (console.log(""), console.log(`${t.includes("does not exist") ? "✗" : "✓"} ${t}`));
|
|
1453
|
-
},
|
|
1519
|
+
}, pn = (e) => e.map((e) => {
|
|
1454
1520
|
let t = e, n = Object.entries(t.fields ?? {}).map(([e, t]) => ({
|
|
1455
1521
|
name: e,
|
|
1456
1522
|
type: typeof t?.type == "string" ? t.type : ""
|
|
@@ -1460,13 +1526,13 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1460
1526
|
columns: n,
|
|
1461
1527
|
primaryKey: t.appliedPrimaryKey ?? []
|
|
1462
1528
|
};
|
|
1463
|
-
}),
|
|
1529
|
+
}), mn = async (e) => {
|
|
1464
1530
|
try {
|
|
1465
1531
|
let { missingRelationSources: t } = await import("./doctorSourceRelations-c5mlN5HI.js"), { sourceKeys: n } = await import("@voltro/protocol"), { readFile: r } = await import("node:fs/promises"), { discovered: i } = await U(e), a = [], o = [];
|
|
1466
1532
|
for (let e of i.queries) {
|
|
1467
1533
|
let i = n(e.descriptor.source);
|
|
1468
1534
|
if (i.length === 0) continue;
|
|
1469
|
-
let s =
|
|
1535
|
+
let s = hn(e.file);
|
|
1470
1536
|
if (s === void 0) continue;
|
|
1471
1537
|
let c = await r(s, "utf8").catch(() => null);
|
|
1472
1538
|
if (c === null) continue;
|
|
@@ -1483,8 +1549,8 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1483
1549
|
} catch {
|
|
1484
1550
|
return null;
|
|
1485
1551
|
}
|
|
1486
|
-
},
|
|
1487
|
-
let t = await
|
|
1552
|
+
}, hn = (e) => e.endsWith(".ts") && !e.endsWith(".server.ts") ? `${e.slice(0, -3)}.server.ts` : void 0, gn = async (e) => {
|
|
1553
|
+
let t = await mn(e);
|
|
1488
1554
|
if (t === null) return;
|
|
1489
1555
|
let n = t.findings;
|
|
1490
1556
|
if (n.length > 0) {
|
|
@@ -1500,11 +1566,11 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1500
1566
|
}, W = async (e) => {
|
|
1501
1567
|
try {
|
|
1502
1568
|
let { discovered: t } = await U(e);
|
|
1503
|
-
return ve(
|
|
1569
|
+
return ve(pn(t.tables));
|
|
1504
1570
|
} catch {
|
|
1505
1571
|
return null;
|
|
1506
1572
|
}
|
|
1507
|
-
},
|
|
1573
|
+
}, _n = async (e) => {
|
|
1508
1574
|
let t = await W(e);
|
|
1509
1575
|
if (t === null || t.tablesChecked === 0) return;
|
|
1510
1576
|
let n = be(t);
|
|
@@ -1524,7 +1590,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1524
1590
|
} catch {
|
|
1525
1591
|
return null;
|
|
1526
1592
|
}
|
|
1527
|
-
},
|
|
1593
|
+
}, vn = async (e) => {
|
|
1528
1594
|
let t = await G(e);
|
|
1529
1595
|
if (t === null || t.eventsChecked === 0) return;
|
|
1530
1596
|
let n = Te(t);
|
|
@@ -1552,7 +1618,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1552
1618
|
}
|
|
1553
1619
|
}, J = async (r) => {
|
|
1554
1620
|
try {
|
|
1555
|
-
let { loadApiConfig: i } = await import("./dev-
|
|
1621
|
+
let { loadApiConfig: i } = await import("./dev-B9Gz0k85.js"), { discovered: a } = await U(r), o = t(await i(r)), s = {
|
|
1556
1622
|
queries: a.queries,
|
|
1557
1623
|
mutations: a.mutations,
|
|
1558
1624
|
actions: a.actions,
|
|
@@ -1574,7 +1640,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1574
1640
|
openAccess: []
|
|
1575
1641
|
};
|
|
1576
1642
|
}
|
|
1577
|
-
},
|
|
1643
|
+
}, yn = async (e) => {
|
|
1578
1644
|
let t = await J(e);
|
|
1579
1645
|
if (!t.checked) return console.log(""), console.log("• access decisions: NOT CHECKED — the app's descriptors could not be loaded (not a pass)"), console.log(` reason: ${t.reason ?? "unknown"}`), !1;
|
|
1580
1646
|
console.log(""), console.log(`access decisions · security.defaultDeny ${t.defaultDeny ? "ON" : "OFF"}`), console.log(` ✗ no access decision ${String(t.undecided.length).padStart(4)}`), console.log(` ✓ openAccess, declared on purpose ${String(t.openAccess.length).padStart(4)}`);
|
|
@@ -1582,8 +1648,8 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1582
1648
|
if (t.undecided.length === 0) return !1;
|
|
1583
1649
|
console.log("");
|
|
1584
1650
|
for (let e of t.undecided) console.log(` ✗ ${e.tag} (${e.kind})${e.file === void 0 ? "" : `\n ${e.file}`}`);
|
|
1585
|
-
return console.log(""), t.defaultDeny ? (console.log(" `voltro dev` and `voltro serve` REFUSE to boot on these. Give each a decision:"),
|
|
1586
|
-
},
|
|
1651
|
+
return console.log(""), t.defaultDeny ? (console.log(" `voltro dev` and `voltro serve` REFUSE to boot on these. Give each a decision:"), bn(), !0) : (console.log(" This app sets `security: { defaultDeny: false }`, so these BOOT — and each one is"), console.log(" callable by any authenticated session. Advisory here for that reason only."), bn(), !1);
|
|
1652
|
+
}, bn = () => {
|
|
1587
1653
|
console.log(" `guards: [{ scope: '…' }]` authority the SUBJECT holds globally"), console.log(" `guards: [{ action, resourceType, resource }]` authority per ROW / per resource"), console.log(" — backed by `defineResourcePolicy` + a tuple source you register. If your"), console.log(" relationships already live in your own tables (a `teamMembers` row), register"), console.log(" a tuple source over them; nothing is copied. Fail-closed without a resolver."), console.log(" Docs: Authentication → Authorization."), console.log(" `openAccess: '<why anyone may call it>'` deliberately unauthenticated");
|
|
1588
1654
|
}, Y = async (e) => {
|
|
1589
1655
|
try {
|
|
@@ -1620,7 +1686,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1620
1686
|
verified: 0
|
|
1621
1687
|
};
|
|
1622
1688
|
}
|
|
1623
|
-
},
|
|
1689
|
+
}, xn = async (e) => {
|
|
1624
1690
|
let t = await Y(e);
|
|
1625
1691
|
if (!t.checked) return console.log(""), console.log("• webhook verification: NOT CHECKED — the app's webhooks could not be loaded (not a pass)"), console.log(` reason: ${t.reason ?? "unknown"}`), !1;
|
|
1626
1692
|
if (t.verified + t.open.length + t.unverified.length === 0) return !1;
|
|
@@ -1630,13 +1696,13 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1630
1696
|
console.log("");
|
|
1631
1697
|
for (let e of t.unverified) console.log(` ✗ ${e.id}\n ${e.file}`);
|
|
1632
1698
|
return console.log(""), console.log(" These are public POSTs that run your application code, and `voltro dev` /"), console.log(" `voltro serve` REFUSE to mount them. Declare one of: `provider:` (a preset),"), console.log(" `signature:` (your own HMAC scheme), `verification: 'provider'` (your handler"), console.log(" verifies), or `verification: 'none'` (deliberately public)."), !0;
|
|
1633
|
-
},
|
|
1699
|
+
}, Sn = async (e) => {
|
|
1634
1700
|
let { status: t, message: n } = await q(e);
|
|
1635
1701
|
return t.checked ? n !== void 0 && (console.log(""), console.log(`✗ [serverOnly] ${n}`), !0) : (console.log(""), console.log("• serverOnly: NOT CHECKED — the app's descriptors could not be loaded (not a pass)"), console.log(` reason: ${t.reason ?? "unknown"}`), console.log(" This audit is the automated check that a hash or a token cannot reach the wire, so"), console.log(" an app that leans on `.serverOnly()` should treat a persistent skip as a failure."), console.log(" `voltro doctor --json` reports it as `serverOnly.checked: false` for a CI gate."), !1);
|
|
1636
|
-
},
|
|
1702
|
+
}, Cn = async (e) => ft({
|
|
1637
1703
|
hasWorkflows: async () => (await U(e)).discovered.workflows.length > 0,
|
|
1638
1704
|
openStore: async () => {
|
|
1639
|
-
let { loadApiConfig: t, buildStore: n } = await import("./dev-
|
|
1705
|
+
let { loadApiConfig: t, buildStore: n } = await import("./dev-B9Gz0k85.js"), r = await t(e);
|
|
1640
1706
|
if (r === null) throw Error("no app.config.ts in this directory");
|
|
1641
1707
|
let i = await n(r, void 0);
|
|
1642
1708
|
return {
|
|
@@ -1650,10 +1716,10 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1650
1716
|
let { sweepStalledRuns: t } = await import("@voltro/workflow");
|
|
1651
1717
|
return t({ store: e });
|
|
1652
1718
|
}
|
|
1653
|
-
}),
|
|
1654
|
-
let t =
|
|
1719
|
+
}), wn = async (e) => {
|
|
1720
|
+
let t = mt(await Cn(e));
|
|
1655
1721
|
t !== null && (console.log(""), console.log(t));
|
|
1656
|
-
},
|
|
1722
|
+
}, Tn = async (e) => {
|
|
1657
1723
|
let t;
|
|
1658
1724
|
try {
|
|
1659
1725
|
let { payloadPropertyNames: n } = await import("@voltro/runtime"), { files: r, discovered: i } = await U(e);
|
|
@@ -1676,13 +1742,13 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1676
1742
|
console.log("");
|
|
1677
1743
|
let r = t.issues.length > 0 ? "✗" : t.unchecked.length > 0 ? "•" : "✓";
|
|
1678
1744
|
console.log(`${r} ${n}`);
|
|
1679
|
-
}, X = "voltro-authz-allowlist.txt",
|
|
1745
|
+
}, X = "voltro-authz-allowlist.txt", En = (e, t = (e) => {
|
|
1680
1746
|
try {
|
|
1681
1747
|
return C(e, "utf8");
|
|
1682
1748
|
} catch {
|
|
1683
1749
|
return "";
|
|
1684
1750
|
}
|
|
1685
|
-
}) => /* @__PURE__ */ new Set([...
|
|
1751
|
+
}) => /* @__PURE__ */ new Set([...Xe, ...Ze(L(e).map(t))]), Dn = (e, t) => {
|
|
1686
1752
|
let n = t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1687
1753
|
return new RegExp(String.raw`(?:export\s+)?const\s+([A-Za-z_$][\w$]*)\s*=\s*define[A-Za-z]*Event\s*\(\s*\{[^}]*?name\s*:\s*['"\`]${n}['"\`]`, "s").exec(e)?.[1];
|
|
1688
1754
|
}, Z = async (e) => {
|
|
@@ -1698,25 +1764,25 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1698
1764
|
} catch {
|
|
1699
1765
|
return "";
|
|
1700
1766
|
}
|
|
1701
|
-
}, a =
|
|
1767
|
+
}, a = L(e).filter((e) => !r.has(e)).map(i).join("\n");
|
|
1702
1768
|
return n.filter(({ name: e, file: t }) => {
|
|
1703
1769
|
if (a.includes(e)) return !1;
|
|
1704
|
-
let n =
|
|
1770
|
+
let n = Dn(i(t), e);
|
|
1705
1771
|
return n === void 0 || !new RegExp(String.raw`\b${n}\b`).test(a);
|
|
1706
1772
|
}).map((e) => e.name).sort();
|
|
1707
1773
|
} catch {
|
|
1708
1774
|
return [];
|
|
1709
1775
|
}
|
|
1710
|
-
},
|
|
1776
|
+
}, On = async (e) => {
|
|
1711
1777
|
let t = await Z(e);
|
|
1712
1778
|
if (t.length !== 0) {
|
|
1713
1779
|
console.log(""), console.log(`• ${t.length} declared event(s) with no emit call site found:`);
|
|
1714
1780
|
for (let e of t) console.log(` ${e}`);
|
|
1715
1781
|
console.log(""), console.log(" An event you declare is an event partners can subscribe to. One that"), console.log(" never fires is indistinguishable, from their side, from a broken"), console.log(" endpoint of their own — so they debug your contract instead of"), console.log(" reading it."), console.log(" ADVISORY: this looks for the event name AND the identifier its"), console.log(" declaration binds it to, so `emit(ctx, apiKeyCreated, …)` counts. An"), console.log(" emit through an ASSEMBLED name still reads as missing here.");
|
|
1716
1782
|
}
|
|
1717
|
-
},
|
|
1783
|
+
}, kn = async (e) => {
|
|
1718
1784
|
try {
|
|
1719
|
-
let { loadApiConfig: t } = await import("./dev-
|
|
1785
|
+
let { loadApiConfig: t } = await import("./dev-B9Gz0k85.js"), n = (await t(e))?.doctor?.scopeVocabulary;
|
|
1720
1786
|
if (typeof n != "string") return [];
|
|
1721
1787
|
let [r, i] = n.split("#");
|
|
1722
1788
|
if (r === void 0 || i === void 0) return [];
|
|
@@ -1733,10 +1799,10 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1733
1799
|
findings: []
|
|
1734
1800
|
});
|
|
1735
1801
|
try {
|
|
1736
|
-
let { offlineManifest: n, toInput: r } = await import("./checkCommand-
|
|
1802
|
+
let { offlineManifest: n, toInput: r } = await import("./checkCommand-D0QV_zM_.js"), { buildAppGraph: i, checkAppGraph: a } = await import("./appGraph-CFmFKHb2.js"), o = await n(e), s = r(o.manifest, o.tables), c = await kn(e), l = [.../* @__PURE__ */ new Set([...s.scopes ?? [], ...c])];
|
|
1737
1803
|
if (l.length === 0) {
|
|
1738
1804
|
try {
|
|
1739
|
-
let { loadAppSchemaInputs: t } = await import("./frameworkTableAssembly-
|
|
1805
|
+
let { loadAppSchemaInputs: t } = await import("./frameworkTableAssembly-CGNC0qr7.js");
|
|
1740
1806
|
await t(e);
|
|
1741
1807
|
} catch {
|
|
1742
1808
|
return t("app-not-importable");
|
|
@@ -1760,7 +1826,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1760
1826
|
} catch {
|
|
1761
1827
|
return t("app-not-importable");
|
|
1762
1828
|
}
|
|
1763
|
-
},
|
|
1829
|
+
}, An = async (e) => {
|
|
1764
1830
|
let { findings: t, evaluated: n, notEvaluated: r } = await Q(e);
|
|
1765
1831
|
if (!n) {
|
|
1766
1832
|
if (console.log(""), r === "app-not-importable") {
|
|
@@ -1775,7 +1841,43 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1775
1841
|
for (let e of t) console.log(` ${e.node}${e.file === void 0 ? "" : ` ${e.file}`}`), console.log(` ${e.detail}`);
|
|
1776
1842
|
console.log(""), console.log(" Each of these is uncallable by every user in every role — not"), console.log(" misconfigured, DEAD — and nothing fails at boot to say so. The"), console.log(" usual cause is a typo or a rename that moved one side only."), console.log(` ${t[0].fix}`);
|
|
1777
1843
|
}
|
|
1778
|
-
},
|
|
1844
|
+
}, jn = (e) => {
|
|
1845
|
+
let t = v(e, "src");
|
|
1846
|
+
if (!S(t)) return;
|
|
1847
|
+
let n = [], r = (t, i = 0) => {
|
|
1848
|
+
if (i > 12 || I.test(t)) return;
|
|
1849
|
+
let a;
|
|
1850
|
+
try {
|
|
1851
|
+
a = w(t);
|
|
1852
|
+
} catch {
|
|
1853
|
+
return;
|
|
1854
|
+
}
|
|
1855
|
+
for (let o of a) {
|
|
1856
|
+
let a = v(t, o), s;
|
|
1857
|
+
try {
|
|
1858
|
+
s = T(a);
|
|
1859
|
+
} catch {
|
|
1860
|
+
continue;
|
|
1861
|
+
}
|
|
1862
|
+
if (s.isDirectory()) {
|
|
1863
|
+
r(a, i + 1);
|
|
1864
|
+
continue;
|
|
1865
|
+
}
|
|
1866
|
+
if (!(!/\.(tsx?|css)$/.test(o) || /\.(test|spec)\./.test(o))) try {
|
|
1867
|
+
n.push({
|
|
1868
|
+
path: y(e, a).split("\\").join("/"),
|
|
1869
|
+
source: C(a, "utf8")
|
|
1870
|
+
});
|
|
1871
|
+
} catch {}
|
|
1872
|
+
}
|
|
1873
|
+
};
|
|
1874
|
+
r(t);
|
|
1875
|
+
let i = yt(_t(n));
|
|
1876
|
+
if (i.length !== 0) {
|
|
1877
|
+
console.log("");
|
|
1878
|
+
for (let e of i) console.log(e);
|
|
1879
|
+
}
|
|
1880
|
+
}, Mn = async (e) => {
|
|
1779
1881
|
let t = ["src/locales", "locales"], n, r = [];
|
|
1780
1882
|
for (let i of t) {
|
|
1781
1883
|
let t = v(e, i);
|
|
@@ -1787,20 +1889,20 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1787
1889
|
if (n === void 0 || r.length === 0) return;
|
|
1788
1890
|
let i = [];
|
|
1789
1891
|
try {
|
|
1790
|
-
let { loadApiConfig: t } = await import("./dev-
|
|
1892
|
+
let { loadApiConfig: t } = await import("./dev-B9Gz0k85.js");
|
|
1791
1893
|
i = (await t(e))?.locales ?? [];
|
|
1792
1894
|
} catch {
|
|
1793
1895
|
return;
|
|
1794
1896
|
}
|
|
1795
|
-
let a =
|
|
1897
|
+
let a = We({
|
|
1796
1898
|
catalogCodes: r,
|
|
1797
1899
|
declaredLocales: i
|
|
1798
1900
|
});
|
|
1799
1901
|
if (a !== void 0) {
|
|
1800
1902
|
console.log("");
|
|
1801
|
-
for (let e of
|
|
1903
|
+
for (let e of Ge(a, n)) console.log(e);
|
|
1802
1904
|
}
|
|
1803
|
-
},
|
|
1905
|
+
}, Nn = async (e) => {
|
|
1804
1906
|
let t = v(e, "src");
|
|
1805
1907
|
if (!S(t)) return;
|
|
1806
1908
|
let n = !1, r = (e) => {
|
|
@@ -1819,9 +1921,9 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1819
1921
|
return;
|
|
1820
1922
|
}
|
|
1821
1923
|
a()?.reason === "binary-missing" ? (console.log("image pipeline: sharp is INSTALLED but its platform binary is missing —"), console.log(" an install that omitted optional dependencies drops the @img/* prebuilds."), console.log(" Fix: reinstall without omitting optional deps, or `pnpm add -D sharp` in this app.")) : (console.log("image pipeline: sharp is NOT installed — ?image imports serve originals (no srcSet, no blur)."), console.log(" Fix: `pnpm add -D sharp` in this app (it is an optional dependency of @voltro/cli;"), console.log(" your installer skipped optional dependencies)."));
|
|
1822
|
-
},
|
|
1924
|
+
}, Pn = async (e) => {
|
|
1823
1925
|
try {
|
|
1824
|
-
let { loadConfig: t } = await import("./webDev-
|
|
1926
|
+
let { loadConfig: t } = await import("./webDev-C2dRz9s5.js"), n = (await t(e, { preferSource: !0 }))?.fonts;
|
|
1825
1927
|
if (n === void 0 || n.length === 0) return;
|
|
1826
1928
|
let { loadFontkit: r, loadSubsetFont: i } = await import("./fontPipeline-LxIHa1vo.js"), a = [];
|
|
1827
1929
|
if (await r() === null && a.push("fontkit (size-adjust fallback metrics — the CLS guard — are skipped)"), await i() === null && a.push("subset-font (declared `subsets:` ship the full files)"), console.log(""), a.length === 0) {
|
|
@@ -1831,25 +1933,25 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1831
1933
|
for (let e of a) console.log(`font pipeline: ${e}`);
|
|
1832
1934
|
console.log(" Fix: reinstall without omitting optional deps, or `pnpm add -D fontkit subset-font` in this app.");
|
|
1833
1935
|
} catch {}
|
|
1834
|
-
},
|
|
1936
|
+
}, Fn = async (e) => {
|
|
1835
1937
|
let t = v(e, "src", "pages");
|
|
1836
1938
|
if (!S(t)) return !1;
|
|
1837
1939
|
let n = [];
|
|
1838
1940
|
try {
|
|
1839
|
-
let { walkPagesTree: e } = await import("./webDev-
|
|
1941
|
+
let { walkPagesTree: e } = await import("./webDev-C2dRz9s5.js");
|
|
1840
1942
|
n = (await e(t)).pages.map((e) => e.pattern);
|
|
1841
1943
|
} catch {
|
|
1842
1944
|
return !1;
|
|
1843
1945
|
}
|
|
1844
|
-
let r =
|
|
1946
|
+
let r = qe(e, n);
|
|
1845
1947
|
if (r === void 0) return !1;
|
|
1846
1948
|
console.log("");
|
|
1847
|
-
for (let e of
|
|
1949
|
+
for (let e of Je(r)) console.log(e);
|
|
1848
1950
|
return r.problems.length > 0;
|
|
1849
|
-
},
|
|
1951
|
+
}, In = async (e) => {
|
|
1850
1952
|
let { discovered: t } = await U(e), n = [];
|
|
1851
1953
|
try {
|
|
1852
|
-
let { loadApiConfig: t } = await import("./dev-
|
|
1954
|
+
let { loadApiConfig: t } = await import("./dev-B9Gz0k85.js");
|
|
1853
1955
|
n = ((await t(e))?.plugins ?? []).map((e) => {
|
|
1854
1956
|
let t = (e.extendSchema?.tables ?? []).map((e) => {
|
|
1855
1957
|
let t = e;
|
|
@@ -1857,13 +1959,13 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1857
1959
|
tableName: typeof t.tableName == "string" ? t.tableName : "",
|
|
1858
1960
|
renamedFrom: typeof t.renamedFrom == "string" ? t.renamedFrom : void 0
|
|
1859
1961
|
};
|
|
1860
|
-
}).filter((e) => e.tableName !== ""), n = (e.rpcClientDescriptors ?? []).map((t) => typeof t.tag == "string" ?
|
|
1962
|
+
}).filter((e) => e.tableName !== ""), n = (e.rpcClientDescriptors ?? []).map((t) => typeof t.tag == "string" ? p(e, t.tag) : "").filter((e) => e !== ""), r = e.baseName ?? e.name;
|
|
1861
1963
|
return {
|
|
1862
1964
|
plugin: e.name,
|
|
1863
1965
|
tables: t,
|
|
1864
1966
|
rpcTags: n,
|
|
1865
|
-
canDisableTables:
|
|
1866
|
-
canAlias:
|
|
1967
|
+
canDisableTables: Ln.has(r),
|
|
1968
|
+
canAlias: Rn.has(r)
|
|
1867
1969
|
};
|
|
1868
1970
|
});
|
|
1869
1971
|
} catch {
|
|
@@ -1875,18 +1977,18 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1875
1977
|
...t.mutations,
|
|
1876
1978
|
...t.actions,
|
|
1877
1979
|
...t.streams ?? []
|
|
1878
|
-
].map((e) => String(e.descriptor.name)), i =
|
|
1980
|
+
].map((e) => String(e.descriptor.name)), i = ut(n, {
|
|
1879
1981
|
tables: t.tables.map((e) => e.tableName),
|
|
1880
1982
|
rpcTags: r
|
|
1881
1983
|
});
|
|
1882
1984
|
console.log();
|
|
1883
|
-
for (let e of
|
|
1884
|
-
},
|
|
1985
|
+
for (let e of dt(n, i)) console.log(e);
|
|
1986
|
+
}, Ln = /* @__PURE__ */ new Set([
|
|
1885
1987
|
"@voltro/plugin-rbac",
|
|
1886
1988
|
"@voltro/plugin-audit",
|
|
1887
1989
|
"@voltro/plugin-notifications",
|
|
1888
1990
|
"aiFlows"
|
|
1889
|
-
]),
|
|
1991
|
+
]), Rn = /* @__PURE__ */ new Set([
|
|
1890
1992
|
"aiFlows",
|
|
1891
1993
|
"@voltro/plugin-audit",
|
|
1892
1994
|
"@voltro/plugin-billing",
|
|
@@ -1904,8 +2006,8 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1904
2006
|
"@voltro/plugin-sso-saml",
|
|
1905
2007
|
"@voltro/plugin-storage",
|
|
1906
2008
|
"@voltro/plugin-row-history"
|
|
1907
|
-
]), $ = 20,
|
|
1908
|
-
let t = await
|
|
2009
|
+
]), $ = 20, zn = async (e) => {
|
|
2010
|
+
let t = await Bn(e), n = new Set(t.reviewed.map((e) => e.tag)), r = t.result.findings.filter((e) => e.verdict.kind === "allowlisted" && !n.has(e.tag)).length;
|
|
1909
2011
|
return {
|
|
1910
2012
|
executors: t.executorCount,
|
|
1911
2013
|
guardVocabulary: [...t.vocabulary].sort(),
|
|
@@ -1917,7 +2019,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1917
2019
|
},
|
|
1918
2020
|
unchecked: t.result.unchecked
|
|
1919
2021
|
};
|
|
1920
|
-
},
|
|
2022
|
+
}, Bn = async (e) => {
|
|
1921
2023
|
let { discovered: t } = await U(e), n = /* @__PURE__ */ new Map(), r = (e) => {
|
|
1922
2024
|
if (!n.has(e)) try {
|
|
1923
2025
|
n.set(e, C(e, "utf8"));
|
|
@@ -1925,7 +2027,7 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1925
2027
|
n.set(e, "");
|
|
1926
2028
|
}
|
|
1927
2029
|
return n.get(e);
|
|
1928
|
-
}, i =
|
|
2030
|
+
}, i = En(e, r), a = /* @__PURE__ */ new Set();
|
|
1929
2031
|
for (let e of t.tables) for (let t of Object.values(e.fields ?? {})) try {
|
|
1930
2032
|
let e = t.references?.();
|
|
1931
2033
|
e && a.add(e.tableName);
|
|
@@ -1957,12 +2059,12 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1957
2059
|
op: a?.op === "delete" || a?.op === "insert" ? a.op : t,
|
|
1958
2060
|
...a?.table === void 0 ? {} : { table: a.table }
|
|
1959
2061
|
};
|
|
1960
|
-
})), s = v(e, X), c = S(s) ?
|
|
1961
|
-
for (let t of
|
|
2062
|
+
})), s = v(e, X), c = S(s) ? j(C(s, "utf8")) : void 0, l = !1;
|
|
2063
|
+
for (let t of L(e)) if (/\bsetRowFilter\s*[<(]/.test(r(t))) {
|
|
1962
2064
|
l = !0;
|
|
1963
2065
|
break;
|
|
1964
2066
|
}
|
|
1965
|
-
let u =
|
|
2067
|
+
let u = rt({
|
|
1966
2068
|
executors: o,
|
|
1967
2069
|
guardVocabulary: i,
|
|
1968
2070
|
tenantScopedTables: t.tenantScopedTables,
|
|
@@ -1979,23 +2081,23 @@ var le = /* @__PURE__ */ new Set([
|
|
|
1979
2081
|
executorCount: o.length,
|
|
1980
2082
|
allowPath: s
|
|
1981
2083
|
};
|
|
1982
|
-
},
|
|
1983
|
-
let { result: n, vocabulary: r, existing: i, reviewed: a, executorCount: o, allowPath: s, rowFilterRegistered: c } = await
|
|
2084
|
+
}, Vn = async (e, t) => {
|
|
2085
|
+
let { result: n, vocabulary: r, existing: i, reviewed: a, executorCount: o, allowPath: s, rowFilterRegistered: c } = await Bn(e), l = n.counts;
|
|
1984
2086
|
console.log(`\nauthz scan · ${o} executor(s)`);
|
|
1985
|
-
let u = [...r].filter((e) => !
|
|
2087
|
+
let u = [...r].filter((e) => !Xe.has(e)).sort();
|
|
1986
2088
|
console.log(u.length === 0 ? " guard vocabulary: framework names only — no exported require*/assert* found in this app" : ` guard vocabulary: ${u.length} from your source (${u.slice(0, 6).join(", ")}${u.length > 6 ? ", …" : ""})`), console.log(` ✗ no access check ${String(l.unchecked).padStart(4)}`), console.log(` ⚠ inline ownership check, no named guard${String(l.inlineOwnership).padStart(4)} (informational)`), console.log(` ✓ guards: on the descriptor ${String(l.declaredGuard).padStart(4)}`), console.log(` ✓ calls a guard from the vocabulary ${String(l.vocabularyGuard).padStart(4)}`);
|
|
1987
2089
|
let d = new Set(a.map((e) => e.tag)), f = n.findings.filter((e) => e.verdict.kind === "allowlisted" && !d.has(e.tag)).length, p = l.allowlisted - f;
|
|
1988
2090
|
if (console.log(` – accepted as recorded debt ${String(f).padStart(4)} (${X})`), console.log(` ✓ reviewed, open on purpose ${String(p).padStart(4)} (\`reviewed=<why>\` in that file)`), c && console.log(" ⓘ this app registers setRowFilter — the scan CANNOT see through it. A finding below may\n already be constrained; verify the filter covers that table and record it as `reviewed=`."), t) {
|
|
1989
|
-
let e = S(s) ? C(s, "utf8") : void 0, t = n.unchecked.map((e) => e.tag), r =
|
|
1990
|
-
return oe(s,
|
|
2091
|
+
let e = S(s) ? C(s, "utf8") : void 0, t = n.unchecked.map((e) => e.tag), r = st(e, t);
|
|
2092
|
+
return oe(s, ot(e, t), "utf8"), console.log(`\n${X}: +${r.added} new, ${r.kept} kept, ${r.removed} removed. Doctor now fails on ADDITIONS only.`), r.added === 0 && console.log(" (nothing new was unchecked — the file is unchanged.)"), !1;
|
|
1991
2093
|
}
|
|
1992
2094
|
if (n.unchecked.length === 0) return !1;
|
|
1993
2095
|
console.log("");
|
|
1994
2096
|
for (let e of n.unchecked.slice(0, $)) console.log(` ✗ ${e.tag} — ${e.why}\n ${e.path}`);
|
|
1995
2097
|
return n.unchecked.length > $ && console.log(` … and ${n.unchecked.length - $} more — \`voltro doctor --json\` prints every one (\`authz.unchecked\`).`), i === void 0 ? (console.log(`\nNo ${X} yet, so this run is advisory. To start the ratchet:`), console.log("\n voltro doctor --write-authz-allowlist\n"), console.log("That records today's unchecked handlers as DEBT and fails every run after on"), console.log("anything NEW. Fix a handler and its line stops mattering — the scan reports it as"), console.log("guarded whether or not the line is still there."), !1) : (console.log(`\n${n.unchecked.length} executor(s) with no access check are not in ${X}.`), console.log("Add a guard, or add the tag to that file if it is genuinely open."), console.log("\nBefore hand-rolling another check: `guards: [{ action, resourceType, resource }]`"), console.log("answers \"may this subject act on THIS row\" declaratively, and an app whose"), console.log("relationships live in its own tables registers its own tuple source rather than"), console.log("copying data into a framework table. See the authorization docs."), !0);
|
|
1996
|
-
},
|
|
2098
|
+
}, Hn = async (e) => {
|
|
1997
2099
|
try {
|
|
1998
|
-
let { loadApiConfig: t } = await import("./dev-
|
|
2100
|
+
let { loadApiConfig: t } = await import("./dev-B9Gz0k85.js"), { decidedSchemaReport: n } = await import("./doctorDecidedSchema-BlbWgCD_.js"), r = await t(e);
|
|
1999
2101
|
return r == null ? null : n({
|
|
2000
2102
|
...r.schema ? { declared: r.schema } : {},
|
|
2001
2103
|
...r.store === void 0 ? {} : { store: r.store },
|
|
@@ -2004,42 +2106,42 @@ var le = /* @__PURE__ */ new Set([
|
|
|
2004
2106
|
} catch {
|
|
2005
2107
|
return null;
|
|
2006
2108
|
}
|
|
2007
|
-
},
|
|
2008
|
-
let t = await
|
|
2109
|
+
}, Un = async (e) => {
|
|
2110
|
+
let t = await Hn(e);
|
|
2009
2111
|
if (t !== null) {
|
|
2010
2112
|
console.log(""), console.log("• framework tables whose presence is DECIDED rather than implied by your source tree:");
|
|
2011
2113
|
for (let e of t.text.split("\n")) console.log(` ${e}`);
|
|
2012
2114
|
}
|
|
2013
|
-
},
|
|
2014
|
-
if (e.includes("--help") || e.includes("-h")) return console.log(
|
|
2015
|
-
let t = e.includes("--strict"), n = e.find((e) => !e.startsWith("-")),
|
|
2115
|
+
}, Wn = async (e) => {
|
|
2116
|
+
if (e.includes("--help") || e.includes("-h")) return console.log(un), 0;
|
|
2117
|
+
let t = e.includes("--strict"), n = e.find((e) => !e.startsWith("-")), r = b(n ?? process.cwd());
|
|
2016
2118
|
if (g(e)) return ee(), h({
|
|
2017
|
-
...
|
|
2018
|
-
spaCandidates: await
|
|
2019
|
-
pageConvention:
|
|
2020
|
-
fileTaxonomy: re(
|
|
2021
|
-
junctionFks: (await W(
|
|
2022
|
-
eventDelivery: await G(
|
|
2023
|
-
duplicateInstances:
|
|
2024
|
-
versionSkew: r
|
|
2025
|
-
serverOnly: (await q(
|
|
2026
|
-
accessDecisions: await J(
|
|
2027
|
-
webhookVerification: await Y(
|
|
2028
|
-
authz: await
|
|
2029
|
-
ungrantedScopes: await Q(
|
|
2030
|
-
neverEmittedEvents: await Z(
|
|
2031
|
-
unimportedDeps:
|
|
2032
|
-
stalledRuns: await
|
|
2033
|
-
decidedSchema: await
|
|
2119
|
+
...R(r),
|
|
2120
|
+
spaCandidates: await z(r),
|
|
2121
|
+
pageConvention: B(r),
|
|
2122
|
+
fileTaxonomy: re(r).findings,
|
|
2123
|
+
junctionFks: (await W(r))?.issues ?? [],
|
|
2124
|
+
eventDelivery: await G(r),
|
|
2125
|
+
duplicateInstances: a(r),
|
|
2126
|
+
versionSkew: o(r) ?? null,
|
|
2127
|
+
serverOnly: (await q(r)).status,
|
|
2128
|
+
accessDecisions: await J(r),
|
|
2129
|
+
webhookVerification: await Y(r),
|
|
2130
|
+
authz: await zn(r),
|
|
2131
|
+
ungrantedScopes: await Q(r),
|
|
2132
|
+
neverEmittedEvents: await Z(r),
|
|
2133
|
+
unimportedDeps: He(r),
|
|
2134
|
+
stalledRuns: await Cn(r),
|
|
2135
|
+
decidedSchema: await Hn(r)
|
|
2034
2136
|
}), 0;
|
|
2035
|
-
let c =
|
|
2036
|
-
|
|
2037
|
-
for (let e of
|
|
2038
|
-
await
|
|
2039
|
-
let l = await
|
|
2137
|
+
let c = Ct(r, t);
|
|
2138
|
+
Zt(r), Xt(r), ln(r), ne(r), await rn(r), await Tn(r), await wn(r), await fn(r), await _n(r), await gn(r), await Un(r), await vn(r), await In(r), await An(r), await On(r), console.log("");
|
|
2139
|
+
for (let e of Ue(He(r))) console.log(e);
|
|
2140
|
+
await Mn(r), jn(r), await Nn(r), await Pn(r);
|
|
2141
|
+
let l = await Sn(r), u = await Vn(r, e.includes("--write-authz-allowlist")), d = await yn(r), f = await xn(r), p = await Fn(r), m = i(o(r));
|
|
2040
2142
|
m !== void 0 && (console.log(""), console.log(m));
|
|
2041
|
-
let _ =
|
|
2143
|
+
let _ = s(a(r));
|
|
2042
2144
|
return _ !== void 0 && console.log(`\n${_}`), l || u || d || p || f ? Math.max(c, 1) : c;
|
|
2043
2145
|
};
|
|
2044
2146
|
//#endregion
|
|
2045
|
-
export {
|
|
2147
|
+
export { z as C, Y as E, B as S, Q as T, ln as _, zn as a, Ct as b, G as c, Wt as d, xt as f, Zt as g, Xt as h, J as i, En as l, mn as m, St as n, Z as o, W as p, Qt as r, Dn as s, un as t, R as u, rn as v, q as w, Gt as x, Wn as y };
|