@safegres/test 0.0.2 → 1.30.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (483) hide show
  1. package/README.md +825 -412
  2. package/adapters.d.ts +8 -0
  3. package/adapters.js +18 -0
  4. package/ast/helpers.d.ts +16 -0
  5. package/ast/helpers.js +40 -0
  6. package/ast/parse.d.ts +31 -0
  7. package/ast/parse.js +87 -0
  8. package/ast/walk.d.ts +27 -0
  9. package/ast/walk.js +79 -0
  10. package/callgraph/baseline.d.ts +28 -0
  11. package/callgraph/baseline.js +55 -0
  12. package/callgraph/extract.d.ts +93 -0
  13. package/callgraph/extract.js +340 -0
  14. package/callgraph/graph.d.ts +82 -0
  15. package/callgraph/graph.js +276 -0
  16. package/checks/anti-patterns.d.ts +53 -0
  17. package/checks/anti-patterns.js +247 -0
  18. package/checks/column-grants.d.ts +20 -0
  19. package/checks/column-grants.js +74 -0
  20. package/checks/coverage.d.ts +43 -0
  21. package/checks/coverage.js +110 -0
  22. package/checks/definer-function.d.ts +91 -0
  23. package/checks/definer-function.js +458 -0
  24. package/checks/definer-view.d.ts +167 -0
  25. package/checks/definer-view.js +392 -0
  26. package/checks/indexes.d.ts +82 -0
  27. package/checks/indexes.js +263 -0
  28. package/checks/lattice.d.ts +179 -0
  29. package/checks/lattice.js +487 -0
  30. package/checks/object-acls.d.ts +32 -0
  31. package/checks/object-acls.js +129 -0
  32. package/checks/policy-index.d.ts +78 -0
  33. package/checks/policy-index.js +349 -0
  34. package/checks/revocable-grants.d.ts +140 -0
  35. package/checks/revocable-grants.js +377 -0
  36. package/checks/rls-flags.d.ts +25 -0
  37. package/checks/rls-flags.js +82 -0
  38. package/checks/role-reach.d.ts +329 -0
  39. package/checks/role-reach.js +277 -0
  40. package/checks/role-trust.d.ts +45 -0
  41. package/checks/role-trust.js +91 -0
  42. package/checks/set-role.d.ts +21 -0
  43. package/checks/set-role.js +66 -0
  44. package/checks/stats.d.ts +52 -0
  45. package/checks/stats.js +192 -0
  46. package/checks/view-exposure.d.ts +68 -0
  47. package/checks/view-exposure.js +236 -0
  48. package/checks/view-writes.d.ts +88 -0
  49. package/checks/view-writes.js +350 -0
  50. package/ci/baseline.d.ts +104 -0
  51. package/ci/baseline.js +111 -0
  52. package/ci/github.d.ts +47 -0
  53. package/ci/github.js +197 -0
  54. package/cli/audit.d.ts +3 -0
  55. package/cli/audit.js +560 -0
  56. package/cli/baseline.d.ts +3 -0
  57. package/cli/baseline.js +104 -0
  58. package/cli/commands.d.ts +2 -0
  59. package/cli/commands.js +60 -0
  60. package/cli/doctor.d.ts +3 -0
  61. package/cli/doctor.js +72 -0
  62. package/cli/eval.d.ts +3 -0
  63. package/cli/eval.js +153 -0
  64. package/cli/print-config.d.ts +3 -0
  65. package/cli/print-config.js +54 -0
  66. package/cli/shared.d.ts +43 -0
  67. package/cli/shared.js +153 -0
  68. package/cli.d.ts +2 -0
  69. package/cli.js +69 -0
  70. package/commands/audit.d.ts +65 -0
  71. package/commands/audit.js +779 -0
  72. package/commands/doctor.d.ts +19 -0
  73. package/commands/doctor.js +181 -0
  74. package/commands/eval.d.ts +67 -0
  75. package/commands/eval.js +93 -0
  76. package/config/fingerprint.d.ts +40 -0
  77. package/config/fingerprint.js +71 -0
  78. package/config/loader.d.ts +44 -0
  79. package/config/loader.js +210 -0
  80. package/config/presets.d.ts +95 -0
  81. package/config/presets.js +327 -0
  82. package/config/resolve.d.ts +47 -0
  83. package/config/resolve.js +192 -0
  84. package/config/schema.d.ts +54 -0
  85. package/config/schema.js +269 -0
  86. package/config/types.d.ts +562 -0
  87. package/config/validate.d.ts +14 -0
  88. package/config/validate.js +125 -0
  89. package/corpus/README.md +83 -0
  90. package/corpus/bootstrap.sql +14 -0
  91. package/corpus/cases/01-anon-write-grant/case.json +26 -0
  92. package/corpus/cases/01-anon-write-grant/schema.sql +19 -0
  93. package/corpus/cases/02-grant-to-public/case.json +25 -0
  94. package/corpus/cases/02-grant-to-public/schema.sql +18 -0
  95. package/corpus/cases/03-rls-off-reachable-by-anon/case.json +30 -0
  96. package/corpus/cases/03-rls-off-reachable-by-anon/schema.sql +13 -0
  97. package/corpus/cases/04-permissive-write-policy/case.json +30 -0
  98. package/corpus/cases/04-permissive-write-policy/schema.sql +21 -0
  99. package/corpus/cases/05-public-read-policy/case.json +25 -0
  100. package/corpus/cases/05-public-read-policy/schema.sql +16 -0
  101. package/corpus/cases/06-update-without-with-check/case.json +25 -0
  102. package/corpus/cases/06-update-without-with-check/schema.sql +19 -0
  103. package/corpus/cases/07-rls-enabled-no-policies/case.json +29 -0
  104. package/corpus/cases/07-rls-enabled-no-policies/schema.sql +14 -0
  105. package/corpus/cases/08-select-grant-no-policy/case.json +25 -0
  106. package/corpus/cases/08-select-grant-no-policy/schema.sql +20 -0
  107. package/corpus/cases/09-write-grant-no-policy/case.json +24 -0
  108. package/corpus/cases/09-write-grant-no-policy/schema.sql +18 -0
  109. package/corpus/cases/10-rls-not-forced/case.json +24 -0
  110. package/corpus/cases/10-rls-not-forced/schema.sql +18 -0
  111. package/corpus/cases/11-session-user-in-policy/case.json +24 -0
  112. package/corpus/cases/11-session-user-in-policy/schema.sql +18 -0
  113. package/corpus/cases/12-volatile-function-in-policy/case.json +24 -0
  114. package/corpus/cases/12-volatile-function-in-policy/schema.sql +21 -0
  115. package/corpus/cases/13-security-definer-policy-wrapper/case.json +24 -0
  116. package/corpus/cases/13-security-definer-policy-wrapper/schema.sql +21 -0
  117. package/corpus/cases/14-dead-policy/case.json +24 -0
  118. package/corpus/cases/14-dead-policy/schema.sql +18 -0
  119. package/corpus/cases/15-unreachable-grant/case.json +24 -0
  120. package/corpus/cases/15-unreachable-grant/schema.sql +18 -0
  121. package/corpus/cases/16-anon-permissive-write-policy/case.json +34 -0
  122. package/corpus/cases/16-anon-permissive-write-policy/schema.sql +17 -0
  123. package/corpus/cases/17-foreign-key-without-index/case.json +24 -0
  124. package/corpus/cases/17-foreign-key-without-index/schema.sql +18 -0
  125. package/corpus/cases/18-policy-column-unindexed/case.json +24 -0
  126. package/corpus/cases/18-policy-column-unindexed/schema.sql +23 -0
  127. package/corpus/cases/19-policy-column-cast/case.json +24 -0
  128. package/corpus/cases/19-policy-column-cast/schema.sql +19 -0
  129. package/corpus/cases/20-stable-function-per-row/case.json +24 -0
  130. package/corpus/cases/20-stable-function-per-row/schema.sql +25 -0
  131. package/corpus/cases/21-table-without-primary-key/case.json +24 -0
  132. package/corpus/cases/21-table-without-primary-key/schema.sql +14 -0
  133. package/corpus/cases/22-redundant-index/case.json +24 -0
  134. package/corpus/cases/22-redundant-index/schema.sql +16 -0
  135. package/corpus/cases/23-tsvector-without-index/case.json +24 -0
  136. package/corpus/cases/23-tsvector-without-index/schema.sql +13 -0
  137. package/corpus/cases/24-anon-set-role-escalation/case.json +29 -0
  138. package/corpus/cases/24-anon-set-role-escalation/schema.sql +30 -0
  139. package/corpus/cases/25-definer-view-bypass/case.json +31 -0
  140. package/corpus/cases/25-definer-view-bypass/schema.sql +36 -0
  141. package/corpus/cases/26-invoker-view-no-bypass/case.json +31 -0
  142. package/corpus/cases/26-invoker-view-no-bypass/schema.sql +44 -0
  143. package/corpus/cases/27-definer-view-write/case.json +36 -0
  144. package/corpus/cases/27-definer-view-write/schema.sql +40 -0
  145. package/corpus/cases/28-invoker-view-no-write/case.json +31 -0
  146. package/corpus/cases/28-invoker-view-no-write/schema.sql +37 -0
  147. package/corpus/cases/29-rewrite-rule-bypass/case.json +36 -0
  148. package/corpus/cases/29-rewrite-rule-bypass/schema.sql +52 -0
  149. package/corpus/cases/30-instead-nothing-rule/case.json +31 -0
  150. package/corpus/cases/30-instead-nothing-rule/schema.sql +44 -0
  151. package/corpus/cases/31-matview-snapshot/case.json +32 -0
  152. package/corpus/cases/31-matview-snapshot/schema.sql +36 -0
  153. package/corpus/cases/32-matview-no-rls-no-bypass/case.json +30 -0
  154. package/corpus/cases/32-matview-no-rls-no-bypass/schema.sql +18 -0
  155. package/corpus/cases/33-leaky-filter-view/case.json +36 -0
  156. package/corpus/cases/33-leaky-filter-view/schema.sql +29 -0
  157. package/corpus/cases/34-barrier-view-no-leak/case.json +32 -0
  158. package/corpus/cases/34-barrier-view-no-leak/schema.sql +29 -0
  159. package/corpus/cases/35-column-grant-projection/case.json +27 -0
  160. package/corpus/cases/35-column-grant-projection/schema.sql +21 -0
  161. package/corpus/cases/35-policy-function-not-leakproof/case.json +24 -0
  162. package/corpus/cases/35-policy-function-not-leakproof/schema.sql +27 -0
  163. package/corpus/cases/36-column-grant-rls-mediated/case.json +27 -0
  164. package/corpus/cases/36-column-grant-rls-mediated/schema.sql +32 -0
  165. package/corpus/cases/36-policy-function-leakproof/case.json +24 -0
  166. package/corpus/cases/36-policy-function-leakproof/schema.sql +22 -0
  167. package/corpus/cases/37-sort-column-unindexed/case.json +24 -0
  168. package/corpus/cases/37-sort-column-unindexed/schema.sql +14 -0
  169. package/corpus/cases/37-unaudited-base-relation/case.json +30 -0
  170. package/corpus/cases/37-unaudited-base-relation/schema.sql +45 -0
  171. package/corpus/cases/38-foreign-key-with-index/case.json +22 -0
  172. package/corpus/cases/38-foreign-key-with-index/schema.sql +17 -0
  173. package/corpus/cases/38-invoker-view-unaudited-base/case.json +30 -0
  174. package/corpus/cases/38-invoker-view-unaudited-base/schema.sql +39 -0
  175. package/corpus/cases/39-definer-view-column-subset/case.json +30 -0
  176. package/corpus/cases/39-definer-view-column-subset/schema.sql +29 -0
  177. package/corpus/cases/39-policy-cast-with-expression-index/case.json +23 -0
  178. package/corpus/cases/39-policy-cast-with-expression-index/schema.sql +19 -0
  179. package/corpus/cases/40-definer-view-column-overreach/case.json +27 -0
  180. package/corpus/cases/40-definer-view-column-overreach/schema.sql +29 -0
  181. package/corpus/cases/40-stable-function-hoisted/case.json +23 -0
  182. package/corpus/cases/40-stable-function-hoisted/schema.sql +25 -0
  183. package/corpus/cases/41-index-prefix-not-redundant/case.json +21 -0
  184. package/corpus/cases/41-index-prefix-not-redundant/schema.sql +15 -0
  185. package/corpus/cases/41-unreadable-view-body/case.json +33 -0
  186. package/corpus/cases/41-unreadable-view-body/schema.sql +28 -0
  187. package/corpus/cases/42-invoker-view-unreadable-body/case.json +30 -0
  188. package/corpus/cases/42-invoker-view-unreadable-body/schema.sql +27 -0
  189. package/corpus/cases/42-search-column-indexed/case.json +21 -0
  190. package/corpus/cases/42-search-column-indexed/schema.sql +12 -0
  191. package/corpus/cases/43-anon-sequence-grant/case.json +27 -0
  192. package/corpus/cases/43-anon-sequence-grant/schema.sql +23 -0
  193. package/corpus/cases/44-serial-sequence-usage/case.json +27 -0
  194. package/corpus/cases/44-serial-sequence-usage/schema.sql +25 -0
  195. package/corpus/cases/45-anon-foreign-table/case.json +27 -0
  196. package/corpus/cases/45-anon-foreign-table/schema.sql +23 -0
  197. package/corpus/cases/46-unchecked-writable-view/case.json +41 -0
  198. package/corpus/cases/46-unchecked-writable-view/schema.sql +37 -0
  199. package/corpus/cases/47-checked-writable-view/case.json +37 -0
  200. package/corpus/cases/47-checked-writable-view/schema.sql +38 -0
  201. package/corpus/cases/48-definer-function-reach/case.json +38 -0
  202. package/corpus/cases/48-definer-function-reach/schema.sql +41 -0
  203. package/corpus/cases/49-invoker-function-no-reach/case.json +32 -0
  204. package/corpus/cases/49-invoker-function-no-reach/schema.sql +38 -0
  205. package/corpus/cases/50-instead-of-trigger-write/case.json +38 -0
  206. package/corpus/cases/50-instead-of-trigger-write/schema.sql +58 -0
  207. package/corpus/cases/51-invoker-trigger-no-write/case.json +33 -0
  208. package/corpus/cases/51-invoker-trigger-no-write/schema.sql +54 -0
  209. package/corpus/cases/52-revocable-execute-grant/case.json +30 -0
  210. package/corpus/cases/52-revocable-execute-grant/schema.sql +45 -0
  211. package/corpus/cases/53-policy-predicate-retains-execute/case.json +23 -0
  212. package/corpus/cases/53-policy-predicate-retains-execute/schema.sql +49 -0
  213. package/corpus/index.d.ts +79 -0
  214. package/corpus/index.js +125 -0
  215. package/esm/adapters.d.ts +8 -0
  216. package/esm/adapters.js +6 -0
  217. package/esm/ast/helpers.d.ts +16 -0
  218. package/esm/ast/helpers.js +36 -0
  219. package/esm/ast/parse.d.ts +31 -0
  220. package/esm/ast/parse.js +82 -0
  221. package/esm/ast/walk.d.ts +27 -0
  222. package/esm/ast/walk.js +72 -0
  223. package/esm/callgraph/baseline.d.ts +28 -0
  224. package/esm/callgraph/baseline.js +48 -0
  225. package/esm/callgraph/extract.d.ts +93 -0
  226. package/esm/callgraph/extract.js +333 -0
  227. package/esm/callgraph/graph.d.ts +82 -0
  228. package/esm/callgraph/graph.js +273 -0
  229. package/esm/checks/anti-patterns.d.ts +53 -0
  230. package/esm/checks/anti-patterns.js +240 -0
  231. package/esm/checks/column-grants.d.ts +20 -0
  232. package/esm/checks/column-grants.js +71 -0
  233. package/esm/checks/coverage.d.ts +43 -0
  234. package/esm/checks/coverage.js +104 -0
  235. package/esm/checks/definer-function.d.ts +91 -0
  236. package/esm/checks/definer-function.js +452 -0
  237. package/esm/checks/definer-view.d.ts +167 -0
  238. package/esm/checks/definer-view.js +382 -0
  239. package/esm/checks/indexes.d.ts +82 -0
  240. package/esm/checks/indexes.js +256 -0
  241. package/esm/checks/lattice.d.ts +179 -0
  242. package/esm/checks/lattice.js +475 -0
  243. package/esm/checks/object-acls.d.ts +32 -0
  244. package/esm/checks/object-acls.js +125 -0
  245. package/esm/checks/policy-index.d.ts +78 -0
  246. package/esm/checks/policy-index.js +342 -0
  247. package/esm/checks/revocable-grants.d.ts +140 -0
  248. package/esm/checks/revocable-grants.js +373 -0
  249. package/esm/checks/rls-flags.d.ts +25 -0
  250. package/esm/checks/rls-flags.js +77 -0
  251. package/esm/checks/role-reach.d.ts +329 -0
  252. package/esm/checks/role-reach.js +270 -0
  253. package/esm/checks/role-trust.d.ts +45 -0
  254. package/esm/checks/role-trust.js +86 -0
  255. package/esm/checks/set-role.d.ts +21 -0
  256. package/esm/checks/set-role.js +63 -0
  257. package/esm/checks/stats.d.ts +52 -0
  258. package/esm/checks/stats.js +184 -0
  259. package/esm/checks/view-exposure.d.ts +68 -0
  260. package/esm/checks/view-exposure.js +231 -0
  261. package/esm/checks/view-writes.d.ts +88 -0
  262. package/esm/checks/view-writes.js +344 -0
  263. package/esm/ci/baseline.d.ts +104 -0
  264. package/esm/ci/baseline.js +107 -0
  265. package/esm/ci/github.d.ts +47 -0
  266. package/esm/ci/github.js +161 -0
  267. package/esm/cli/audit.d.ts +3 -0
  268. package/esm/cli/audit.js +525 -0
  269. package/esm/cli/baseline.d.ts +3 -0
  270. package/esm/cli/baseline.js +102 -0
  271. package/esm/cli/commands.d.ts +2 -0
  272. package/esm/cli/commands.js +53 -0
  273. package/esm/cli/doctor.d.ts +3 -0
  274. package/esm/cli/doctor.js +67 -0
  275. package/esm/cli/eval.d.ts +3 -0
  276. package/esm/cli/eval.js +115 -0
  277. package/esm/cli/print-config.d.ts +3 -0
  278. package/esm/cli/print-config.js +52 -0
  279. package/esm/cli/shared.d.ts +43 -0
  280. package/esm/cli/shared.js +112 -0
  281. package/esm/cli.d.ts +2 -0
  282. package/esm/cli.js +67 -0
  283. package/esm/commands/audit.d.ts +65 -0
  284. package/esm/commands/audit.js +776 -0
  285. package/esm/commands/doctor.d.ts +19 -0
  286. package/esm/commands/doctor.js +178 -0
  287. package/esm/commands/eval.d.ts +67 -0
  288. package/esm/commands/eval.js +90 -0
  289. package/esm/config/fingerprint.d.ts +40 -0
  290. package/esm/config/fingerprint.js +68 -0
  291. package/esm/config/loader.d.ts +44 -0
  292. package/esm/config/loader.js +172 -0
  293. package/esm/config/presets.d.ts +95 -0
  294. package/esm/config/presets.js +324 -0
  295. package/esm/config/resolve.d.ts +47 -0
  296. package/esm/config/resolve.js +180 -0
  297. package/esm/config/schema.d.ts +54 -0
  298. package/esm/config/schema.js +265 -0
  299. package/esm/config/types.d.ts +562 -0
  300. package/esm/config/validate.d.ts +14 -0
  301. package/esm/config/validate.js +122 -0
  302. package/esm/corpus/index.d.ts +79 -0
  303. package/esm/corpus/index.js +85 -0
  304. package/esm/exposure/adapters.d.ts +152 -0
  305. package/esm/exposure/adapters.js +463 -0
  306. package/esm/exposure/planes.d.ts +59 -0
  307. package/esm/exposure/planes.js +144 -0
  308. package/esm/exposure/reach.d.ts +78 -0
  309. package/esm/exposure/reach.js +105 -0
  310. package/esm/exposure/routines.d.ts +36 -0
  311. package/esm/exposure/routines.js +54 -0
  312. package/esm/index.d.ts +96 -0
  313. package/esm/index.js +57 -6
  314. package/esm/lint/index.d.ts +11 -0
  315. package/esm/lint/index.js +10 -0
  316. package/esm/perf/baseline.d.ts +40 -0
  317. package/esm/perf/baseline.js +83 -0
  318. package/esm/perf/explain.d.ts +46 -0
  319. package/esm/perf/explain.js +201 -0
  320. package/esm/pg/acl.d.ts +72 -0
  321. package/esm/pg/acl.js +186 -0
  322. package/esm/pg/behaviors.d.ts +114 -0
  323. package/esm/pg/behaviors.js +206 -0
  324. package/esm/pg/exposure.d.ts +74 -0
  325. package/esm/pg/exposure.js +198 -0
  326. package/esm/pg/functions.d.ts +52 -0
  327. package/esm/pg/functions.js +128 -0
  328. package/esm/pg/indexes.d.ts +192 -0
  329. package/esm/pg/indexes.js +395 -0
  330. package/esm/pg/introspect.d.ts +134 -0
  331. package/esm/pg/introspect.js +274 -0
  332. package/esm/pg/objects.d.ts +37 -0
  333. package/esm/pg/objects.js +108 -0
  334. package/esm/pg/paths.d.ts +114 -0
  335. package/esm/pg/paths.js +159 -0
  336. package/esm/pg/proc.d.ts +23 -0
  337. package/esm/pg/proc.js +55 -0
  338. package/esm/pg/reach-inputs.d.ts +47 -0
  339. package/esm/pg/reach-inputs.js +133 -0
  340. package/esm/pg/roles.d.ts +28 -0
  341. package/esm/pg/roles.js +50 -0
  342. package/esm/pg/stats.d.ts +65 -0
  343. package/esm/pg/stats.js +129 -0
  344. package/esm/pgpm-test.d.ts +22 -0
  345. package/esm/pgpm-test.js +39 -0
  346. package/esm/report/callgraph.d.ts +9 -0
  347. package/esm/report/callgraph.js +74 -0
  348. package/esm/report/compare.d.ts +143 -0
  349. package/esm/report/compare.js +195 -0
  350. package/esm/report/github.d.ts +74 -0
  351. package/esm/report/github.js +290 -0
  352. package/esm/report/json.d.ts +4 -0
  353. package/esm/report/json.js +3 -0
  354. package/esm/report/markdown.d.ts +25 -0
  355. package/esm/report/markdown.js +352 -0
  356. package/esm/report/pretty.d.ts +14 -0
  357. package/esm/report/pretty.js +318 -0
  358. package/esm/report/sarif.d.ts +40 -0
  359. package/esm/report/sarif.js +189 -0
  360. package/esm/report/view.d.ts +82 -0
  361. package/esm/report/view.js +126 -0
  362. package/esm/rules/registry.d.ts +66 -0
  363. package/esm/rules/registry.js +562 -0
  364. package/esm/score/score.d.ts +84 -0
  365. package/esm/score/score.js +233 -0
  366. package/esm/score/scorecards.d.ts +68 -0
  367. package/esm/score/scorecards.js +157 -0
  368. package/esm/types.d.ts +292 -0
  369. package/esm/types.js +26 -0
  370. package/esm/version.d.ts +8 -0
  371. package/esm/version.js +9 -0
  372. package/exposure/adapters.d.ts +152 -0
  373. package/exposure/adapters.js +468 -0
  374. package/exposure/planes.d.ts +59 -0
  375. package/exposure/planes.js +151 -0
  376. package/exposure/reach.d.ts +78 -0
  377. package/exposure/reach.js +109 -0
  378. package/exposure/routines.d.ts +36 -0
  379. package/exposure/routines.js +57 -0
  380. package/index.d.ts +96 -6
  381. package/index.js +229 -6
  382. package/lint/index.d.ts +11 -0
  383. package/lint/index.js +19 -0
  384. package/package.json +54 -48
  385. package/perf/baseline.d.ts +40 -0
  386. package/perf/baseline.js +92 -0
  387. package/perf/explain.d.ts +46 -0
  388. package/perf/explain.js +204 -0
  389. package/pg/acl.d.ts +72 -0
  390. package/pg/acl.js +191 -0
  391. package/pg/behaviors.d.ts +114 -0
  392. package/pg/behaviors.js +217 -0
  393. package/pg/exposure.d.ts +74 -0
  394. package/pg/exposure.js +205 -0
  395. package/pg/functions.d.ts +52 -0
  396. package/pg/functions.js +131 -0
  397. package/pg/indexes.d.ts +192 -0
  398. package/pg/indexes.js +400 -0
  399. package/pg/introspect.d.ts +134 -0
  400. package/pg/introspect.js +280 -0
  401. package/pg/objects.d.ts +37 -0
  402. package/pg/objects.js +111 -0
  403. package/pg/paths.d.ts +114 -0
  404. package/pg/paths.js +166 -0
  405. package/pg/proc.d.ts +23 -0
  406. package/pg/proc.js +58 -0
  407. package/pg/reach-inputs.d.ts +47 -0
  408. package/pg/reach-inputs.js +136 -0
  409. package/pg/roles.d.ts +28 -0
  410. package/pg/roles.js +54 -0
  411. package/pg/stats.d.ts +65 -0
  412. package/pg/stats.js +133 -0
  413. package/pgpm-test.d.ts +22 -0
  414. package/pgpm-test.js +42 -0
  415. package/report/callgraph.d.ts +9 -0
  416. package/report/callgraph.js +81 -0
  417. package/report/compare.d.ts +143 -0
  418. package/report/compare.js +205 -0
  419. package/report/github.d.ts +74 -0
  420. package/report/github.js +333 -0
  421. package/report/json.d.ts +4 -0
  422. package/report/json.js +6 -0
  423. package/report/markdown.d.ts +25 -0
  424. package/report/markdown.js +355 -0
  425. package/report/pretty.d.ts +14 -0
  426. package/report/pretty.js +324 -0
  427. package/report/sarif.d.ts +40 -0
  428. package/report/sarif.js +193 -0
  429. package/report/view.d.ts +82 -0
  430. package/report/view.js +132 -0
  431. package/rules/registry.d.ts +66 -0
  432. package/rules/registry.js +569 -0
  433. package/schema/safegres.schema.json +1119 -0
  434. package/score/score.d.ts +84 -0
  435. package/score/score.js +238 -0
  436. package/score/scorecards.d.ts +68 -0
  437. package/score/scorecards.js +162 -0
  438. package/types.d.ts +292 -0
  439. package/types.js +32 -0
  440. package/version.d.ts +8 -0
  441. package/version.js +12 -0
  442. package/LICENSE +0 -23
  443. package/admin.d.ts +0 -26
  444. package/admin.js +0 -182
  445. package/connect.d.ts +0 -19
  446. package/connect.js +0 -83
  447. package/dist/README.md +0 -557
  448. package/dist/package.json +0 -72
  449. package/esm/admin.js +0 -178
  450. package/esm/connect.js +0 -78
  451. package/esm/manager.js +0 -136
  452. package/esm/roles.js +0 -32
  453. package/esm/seed/adapters.js +0 -23
  454. package/esm/seed/csv.js +0 -44
  455. package/esm/seed/index.js +0 -16
  456. package/esm/seed/json.js +0 -18
  457. package/esm/seed/launchql.js +0 -19
  458. package/esm/seed/sqitch.js +0 -17
  459. package/esm/stream.js +0 -43
  460. package/esm/test-client.js +0 -150
  461. package/manager.d.ts +0 -25
  462. package/manager.js +0 -140
  463. package/roles.d.ts +0 -17
  464. package/roles.js +0 -38
  465. package/seed/adapters.d.ts +0 -4
  466. package/seed/adapters.js +0 -28
  467. package/seed/csv.d.ts +0 -9
  468. package/seed/csv.js +0 -49
  469. package/seed/index.d.ts +0 -16
  470. package/seed/index.js +0 -33
  471. package/seed/json.d.ts +0 -6
  472. package/seed/json.js +0 -21
  473. package/seed/launchql.d.ts +0 -2
  474. package/seed/launchql.js +0 -22
  475. package/seed/sqitch.d.ts +0 -2
  476. package/seed/sqitch.js +0 -20
  477. package/seed/types.d.ts +0 -13
  478. package/stream.d.ts +0 -2
  479. package/stream.js +0 -46
  480. package/test-client.d.ts +0 -49
  481. package/test-client.js +0 -154
  482. /package/{seed → config}/types.js +0 -0
  483. /package/esm/{seed → config}/types.js +0 -0
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.commands = void 0;
7
+ const logger_1 = require("@pgpmjs/logger");
8
+ const inquirerer_1 = require("inquirerer");
9
+ const audit_1 = __importDefault(require("./audit"));
10
+ const baseline_1 = __importDefault(require("./baseline"));
11
+ const doctor_1 = __importDefault(require("./doctor"));
12
+ const eval_1 = __importDefault(require("./eval"));
13
+ const print_config_1 = __importDefault(require("./print-config"));
14
+ const log = new logger_1.Logger('safegres');
15
+ const usage = `
16
+ safegres — Postgres security and performance auditor
17
+
18
+ Usage:
19
+ safegres <command> [OPTIONS]
20
+
21
+ Commands:
22
+ audit Audit grants, RLS flags, policy coverage, and anti-patterns
23
+ lint Alias for audit, for a package.json script
24
+ perf Audit index hygiene and policy cost (audit --perf)
25
+ baseline Choose the report a delta is measured against (CI)
26
+ doctor Diagnose environment, connection, and configuration
27
+ eval Grade the auditor against a corpus with known answers
28
+ print-config Show the resolved effective configuration
29
+ help Show this help message
30
+
31
+ Run \`safegres <command> --help\` for command-specific options.
32
+ `;
33
+ const commandMap = {
34
+ audit: audit_1.default,
35
+ lint: audit_1.default,
36
+ perf: (argv, prompter, options) => (0, audit_1.default)({ ...argv, perf: true }, prompter, options),
37
+ baseline: baseline_1.default,
38
+ doctor: doctor_1.default,
39
+ eval: eval_1.default,
40
+ 'print-config': print_config_1.default
41
+ };
42
+ const commands = async (argv, prompter, options) => {
43
+ const { first: command, newArgv } = (0, inquirerer_1.extractFirst)(argv);
44
+ if (!command && (argv.help || argv.h)) {
45
+ process.stdout.write(usage);
46
+ return;
47
+ }
48
+ if (!command || command === 'help') {
49
+ process.stdout.write(usage);
50
+ return;
51
+ }
52
+ const handler = commandMap[command];
53
+ if (!handler) {
54
+ log.error(`Unknown command: ${command}`);
55
+ process.stdout.write(usage);
56
+ process.exit(2);
57
+ }
58
+ await handler(newArgv, prompter, options);
59
+ };
60
+ exports.commands = commands;
@@ -0,0 +1,3 @@
1
+ import { CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer';
2
+ declare const _default: (argv: ParsedArgs, _prompter: Inquirerer, _options: CLIOptions) => Promise<void>;
3
+ export default _default;
package/cli/doctor.js ADDED
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const yanse_1 = __importDefault(require("yanse"));
7
+ const doctor_1 = require("../commands/doctor");
8
+ const shared_1 = require("./shared");
9
+ const usage = `
10
+ safegres doctor — diagnose the environment, connection, and configuration
11
+
12
+ safegres doctor [OPTIONS]
13
+
14
+ Connection (same flags as \`safegres audit\`):
15
+ --connection <url> Full PostgreSQL connection string
16
+ --host / --port / --user / --password / --database
17
+
18
+ Configuration:
19
+ --config <path> Explicit config file
20
+ --preset <name> Apply a built-in preset
21
+ --rule <CODE=SETTING> Retune a rule (repeatable)
22
+
23
+ Options:
24
+ --no-color Disable ANSI colors
25
+ --help, -h Show this help message
26
+
27
+ Checks: config discovery & rule validation, pgsql-parser availability,
28
+ connection, catalog access (pg_policy), audit blind spots (BYPASSRLS),
29
+ and whether any tables actually have RLS enabled.
30
+ `;
31
+ const STATUS_LABEL = {
32
+ ok: 'OK ',
33
+ warn: 'WARN',
34
+ fail: 'FAIL'
35
+ };
36
+ exports.default = async (argv, _prompter, _options) => {
37
+ if (argv.help || argv.h) {
38
+ process.stdout.write(usage);
39
+ return;
40
+ }
41
+ const colorEnabled = argv.color !== false;
42
+ const paint = (status, s) => {
43
+ if (!colorEnabled)
44
+ return s;
45
+ if (status === 'ok')
46
+ return yanse_1.default.green(s);
47
+ if (status === 'warn')
48
+ return yanse_1.default.yellow(s);
49
+ return yanse_1.default.bold(yanse_1.default.red(s));
50
+ };
51
+ let client = (0, shared_1.buildClient)(argv);
52
+ try {
53
+ await client.connect();
54
+ }
55
+ catch {
56
+ client = null;
57
+ }
58
+ try {
59
+ const report = await (0, doctor_1.doctor)(client, (0, shared_1.configParamsFromArgv)(argv));
60
+ for (const check of report.checks) {
61
+ process.stdout.write(`[${paint(check.status, STATUS_LABEL[check.status])}] ${check.name.padEnd(12)} ${check.detail}\n`);
62
+ }
63
+ process.stdout.write('\n');
64
+ process.stdout.write(report.ok ? 'doctor: all checks passed\n' : 'doctor: some checks failed\n');
65
+ if (!report.ok)
66
+ process.exit(1);
67
+ }
68
+ finally {
69
+ if (client)
70
+ await client.end();
71
+ }
72
+ };
package/cli/eval.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer';
2
+ declare const _default: (argv: ParsedArgs, _prompter: Inquirerer, _options: CLIOptions) => Promise<void>;
3
+ export default _default;
package/cli/eval.js ADDED
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const path = __importStar(require("path"));
40
+ const yanse_1 = __importDefault(require("yanse"));
41
+ const eval_1 = require("../commands/eval");
42
+ const loader_1 = require("../config/loader");
43
+ const corpus_1 = require("../corpus");
44
+ const shared_1 = require("./shared");
45
+ const usage = `
46
+ safegres eval — grade the auditor against a corpus with known answers
47
+
48
+ safegres eval [OPTIONS]
49
+
50
+ Deploys each corpus case into the connected database, audits it under a sealed
51
+ preset, and grades the report against the case's answer key: every expected
52
+ finding present (recall), nothing the case forbids (precision). Exits non-zero
53
+ if any case fails. Each case's schemas are dropped afterwards.
54
+
55
+ Connection (same flags as \`safegres audit\`):
56
+ --connection <url> Full PostgreSQL connection string
57
+ --host / --port / --user / --password / --database
58
+
59
+ Options:
60
+ --preset <name> Preset every case is graded under (default: recommended)
61
+ --corpus <dir> Corpus directory of <id>/{case.json,schema.sql}
62
+ --case <id> Run only these cases; id or id prefix, comma-separated
63
+ --list List the corpus without connecting to a database
64
+ --keep Leave the case schemas in the database
65
+ --json Emit the machine-readable result instead of a table
66
+ --no-color Disable ANSI colors
67
+ --help, -h Show this help message
68
+
69
+ Config: a discovered safegres config may set \`eval.corpus\`, \`eval.preset\` and
70
+ \`eval.cases\` — what to run. It cannot retune the rules: cases are always
71
+ graded by the named preset alone, or the corpus would be measuring itself.
72
+ `;
73
+ /**
74
+ * Discovery is used for *selection only* (which corpus, which preset, which
75
+ * cases). Grading always loads the preset sealed, so nothing in the working
76
+ * tree can change the answers.
77
+ */
78
+ function evalDefaults(configFile) {
79
+ try {
80
+ const loaded = (0, loader_1.loadConfig)({ configFile });
81
+ const config = loaded.config.eval ?? {};
82
+ if (config.corpus === undefined)
83
+ return config;
84
+ // Like every other configured path: relative to the file that declared it,
85
+ // so a corpus committed next to the config is found from any cwd.
86
+ return { ...config, corpus: path.resolve((0, loader_1.configPathBase)(loaded).dirFor('eval.corpus'), config.corpus) };
87
+ }
88
+ catch {
89
+ return {};
90
+ }
91
+ }
92
+ function line(r, color) {
93
+ const paint = (s) => (!color ? s : r.passed ? yanse_1.default.green(s) : yanse_1.default.bold(yanse_1.default.red(s)));
94
+ const detail = r.passed
95
+ ? r.found.map((e) => e.code).join(' ')
96
+ : [
97
+ ...r.missed.map((e) => `missed ${e.code}${e.relation ? `@${e.relation}` : ''}`),
98
+ ...r.falsePositives.map((code) => `false positive ${code}`)
99
+ ].join(', ');
100
+ return ` ${paint(r.passed ? 'PASS' : 'FAIL')} ${r.id.padEnd(32)} ${r.dimension.padEnd(8)} `
101
+ + `${String(r.score).padStart(3)} (${r.grade.padEnd(2)}) ${detail}\n`;
102
+ }
103
+ function summary(report, color) {
104
+ const pct = (n) => `${Math.round(n * 100)}%`;
105
+ const ok = report.passed === report.total;
106
+ const headline = `${report.passed}/${report.total} cases passed`;
107
+ return `\n${color ? (ok ? yanse_1.default.green(headline) : yanse_1.default.bold(yanse_1.default.red(headline))) : headline}`
108
+ + ` · recall ${pct(report.recall)} · precision ${pct(report.precision)}\n`;
109
+ }
110
+ exports.default = async (argv, _prompter, _options) => {
111
+ if (argv.help || argv.h) {
112
+ process.stdout.write(usage);
113
+ return;
114
+ }
115
+ const defaults = evalDefaults(typeof argv.config === 'string' ? argv.config : undefined);
116
+ const corpus = typeof argv.corpus === 'string' ? argv.corpus : defaults.corpus;
117
+ const preset = typeof argv.preset === 'string' ? argv.preset : (defaults.preset ?? 'recommended');
118
+ const cases = (0, shared_1.csvList)(argv.case) ?? defaults.cases;
119
+ const color = argv.color !== false && argv.json !== true;
120
+ if (argv.list === true) {
121
+ for (const c of (0, corpus_1.loadCorpus)(corpus)) {
122
+ process.stdout.write(`${c.id.padEnd(32)} ${c.dimension.padEnd(8)} ${c.title}\n`);
123
+ }
124
+ return;
125
+ }
126
+ const { config } = (0, loader_1.loadConfig)({ sealed: true, preset });
127
+ const client = (0, shared_1.buildClient)(argv);
128
+ await client.connect();
129
+ try {
130
+ const report = await (0, eval_1.runEval)(client, {
131
+ config,
132
+ preset,
133
+ corpus,
134
+ cases,
135
+ keep: argv.keep === true,
136
+ onResult: argv.json === true ? undefined : (r) => process.stdout.write(line(r, color))
137
+ });
138
+ if (argv.json === true) {
139
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
140
+ }
141
+ else {
142
+ process.stdout.write(summary(report, color));
143
+ for (const r of report.results.filter((x) => !x.passed)) {
144
+ process.stdout.write(`\n${r.id}: ${r.title}\n fix: ${r.fix}\n`);
145
+ }
146
+ }
147
+ if (report.passed !== report.total)
148
+ process.exit(1);
149
+ }
150
+ finally {
151
+ await client.end();
152
+ }
153
+ };
@@ -0,0 +1,3 @@
1
+ import { CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer';
2
+ declare const _default: (argv: ParsedArgs, _prompter: Inquirerer, _options: CLIOptions) => Promise<void>;
3
+ export default _default;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const loader_1 = require("../config/loader");
4
+ const resolve_1 = require("../config/resolve");
5
+ const schema_1 = require("../config/schema");
6
+ const registry_1 = require("../rules/registry");
7
+ const shared_1 = require("./shared");
8
+ const usage = `
9
+ safegres print-config — show the resolved effective configuration
10
+
11
+ safegres print-config [OPTIONS]
12
+
13
+ Options:
14
+ --config <path> Explicit config file
15
+ --preset <name> Apply a built-in preset
16
+ --rule <CODE=SETTING> Retune a rule (repeatable)
17
+ --explain Show per-key provenance (which layer set each value)
18
+ --schema Print the config JSON Schema instead, for an editor
19
+ --help, -h Show this help message
20
+ `;
21
+ exports.default = async (argv, _prompter, _options) => {
22
+ if (argv.help || argv.h) {
23
+ process.stdout.write(usage);
24
+ return;
25
+ }
26
+ if (argv.schema === true) {
27
+ process.stdout.write(`${JSON.stringify((0, schema_1.toJsonSchema)(), null, 2)}\n`);
28
+ return;
29
+ }
30
+ const params = (0, shared_1.configParamsFromArgv)(argv);
31
+ if (argv.explain === true) {
32
+ const loader = (0, loader_1.safegresConfigLoader)();
33
+ const explained = loader.explainSync({
34
+ configFile: params.configFile,
35
+ overrides: params.overrides
36
+ });
37
+ for (const e of explained) {
38
+ process.stdout.write(`${e.path} = ${JSON.stringify(e.value)} (${e.source}: ${e.origin})\n`);
39
+ }
40
+ return;
41
+ }
42
+ const { config, filepath, isEmpty } = (0, loader_1.loadConfig)(params);
43
+ const resolved = (0, resolve_1.resolveRules)(config);
44
+ const effectiveRules = {};
45
+ for (const rule of registry_1.RULES) {
46
+ const r = resolved.rules.get(rule.code);
47
+ effectiveRules[rule.code] = r.enabled ? r.severity : 'off';
48
+ }
49
+ process.stdout.write(`${JSON.stringify({
50
+ source: filepath ?? (isEmpty ? '(no config file — defaults)' : undefined),
51
+ config,
52
+ effectiveRules
53
+ }, null, 2)}\n`);
54
+ };
@@ -0,0 +1,43 @@
1
+ import type { ParsedArgs } from 'inquirerer';
2
+ import { Client } from 'pg';
3
+ import type { ConfigPathBase, LoadConfigParams } from '../config/loader';
4
+ import type { ExtensionsConfig, RulesConfig, SafegresConfig } from '../config/types';
5
+ export declare function csvList(value: unknown): string[] | undefined;
6
+ /**
7
+ * Merge `--ignore-extensions` / `--audit-extension-owned` over the config's
8
+ * `extensions` block. Returns `undefined` when neither side says anything, so
9
+ * the introspection defaults apply.
10
+ */
11
+ export declare function extensionScopeFromArgv(argv: ParsedArgs, config: SafegresConfig): ExtensionsConfig | undefined;
12
+ export declare function buildClient(argv: ParsedArgs): Client;
13
+ /**
14
+ * Parse repeatable `--rule CODE=SETTING` flags into a RulesConfig, e.g.
15
+ * `--rule A3=off --rule A5=high --rule 'P*'=off`.
16
+ */
17
+ export declare function parseRuleFlags(value: unknown): RulesConfig | undefined;
18
+ /** Every file a run reads or writes, after flags and config have been merged. */
19
+ export interface RunPaths {
20
+ /** The pgpm workspace to deploy, when `usePgpm`. Undefined means "nearest". */
21
+ pgpm?: string;
22
+ usePgpm: boolean;
23
+ perfBaseline?: string;
24
+ callGraphBaseline?: string;
25
+ outputs: {
26
+ json?: string;
27
+ markdown?: string;
28
+ sarif?: string;
29
+ sarifSources?: string;
30
+ snapshot?: string;
31
+ githubComment?: string;
32
+ };
33
+ }
34
+ /**
35
+ * Flags win over the config file. A path from a config file is resolved
36
+ * against *the file that declared it* — which is not always the discovered
37
+ * one, since a file can extend another — so a CI job can run from any
38
+ * directory; a path on the command line stays relative to cwd, like every
39
+ * other command's arguments.
40
+ */
41
+ export declare function resolveRunPaths(argv: ParsedArgs, config: SafegresConfig, base: ConfigPathBase | string): RunPaths;
42
+ /** Build config-loading params from shared CLI flags. */
43
+ export declare function configParamsFromArgv(argv: ParsedArgs): LoadConfigParams;
package/cli/shared.js ADDED
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.csvList = csvList;
37
+ exports.extensionScopeFromArgv = extensionScopeFromArgv;
38
+ exports.buildClient = buildClient;
39
+ exports.parseRuleFlags = parseRuleFlags;
40
+ exports.resolveRunPaths = resolveRunPaths;
41
+ exports.configParamsFromArgv = configParamsFromArgv;
42
+ const path = __importStar(require("path"));
43
+ const pg_1 = require("pg");
44
+ const pg_env_1 = require("pg-env");
45
+ function csvList(value) {
46
+ if (typeof value !== 'string' || value.length === 0)
47
+ return undefined;
48
+ return value
49
+ .split(',')
50
+ .map((p) => p.trim())
51
+ .filter(Boolean);
52
+ }
53
+ /**
54
+ * Merge `--ignore-extensions` / `--audit-extension-owned` over the config's
55
+ * `extensions` block. Returns `undefined` when neither side says anything, so
56
+ * the introspection defaults apply.
57
+ */
58
+ function extensionScopeFromArgv(argv, config) {
59
+ const ignore = csvList(argv['ignore-extensions']) ?? config.extensions?.ignore;
60
+ const skipOwned = argv['audit-extension-owned'] === true ? false : config.extensions?.skipOwned;
61
+ if (ignore === undefined && skipOwned === undefined)
62
+ return undefined;
63
+ return { ...(ignore !== undefined && { ignore }), ...(skipOwned !== undefined && { skipOwned }) };
64
+ }
65
+ function buildClient(argv) {
66
+ if (typeof argv.connection === 'string' && argv.connection.length > 0) {
67
+ return new pg_1.Client({ connectionString: argv.connection });
68
+ }
69
+ const overrides = {};
70
+ if (typeof argv.host === 'string')
71
+ overrides.host = argv.host;
72
+ if (typeof argv.port === 'number')
73
+ overrides.port = argv.port;
74
+ if (typeof argv.user === 'string')
75
+ overrides.user = argv.user;
76
+ if (typeof argv.password === 'string')
77
+ overrides.password = argv.password;
78
+ if (typeof argv.database === 'string')
79
+ overrides.database = argv.database;
80
+ return new pg_1.Client((0, pg_env_1.getPgEnvOptions)(overrides));
81
+ }
82
+ /**
83
+ * Parse repeatable `--rule CODE=SETTING` flags into a RulesConfig, e.g.
84
+ * `--rule A3=off --rule A5=high --rule 'P*'=off`.
85
+ */
86
+ function parseRuleFlags(value) {
87
+ if (value == null)
88
+ return undefined;
89
+ const entries = Array.isArray(value) ? value : [value];
90
+ const rules = {};
91
+ for (const entry of entries) {
92
+ if (typeof entry !== 'string')
93
+ continue;
94
+ const eq = entry.indexOf('=');
95
+ if (eq <= 0) {
96
+ throw new Error(`Invalid --rule "${entry}": expected CODE=off|<severity>.`);
97
+ }
98
+ const code = entry.slice(0, eq).trim();
99
+ const setting = entry.slice(eq + 1).trim();
100
+ rules[code] = setting;
101
+ }
102
+ return Object.keys(rules).length > 0 ? rules : undefined;
103
+ }
104
+ /** Did the caller name a database on the command line, rather than in the environment? */
105
+ function hasConnectionFlag(argv) {
106
+ return ['connection', 'database', 'host', 'port'].some((flag) => typeof argv[flag] === 'string' || typeof argv[flag] === 'number');
107
+ }
108
+ /**
109
+ * Flags win over the config file. A path from a config file is resolved
110
+ * against *the file that declared it* — which is not always the discovered
111
+ * one, since a file can extend another — so a CI job can run from any
112
+ * directory; a path on the command line stays relative to cwd, like every
113
+ * other command's arguments.
114
+ */
115
+ function resolveRunPaths(argv, config, base) {
116
+ const dirFor = typeof base === 'string' ? () => base : (key) => base.dirFor(key);
117
+ const pick = (flag, key, configured) => typeof flag === 'string' ? flag : configured && path.resolve(dirFor(key), configured);
118
+ // A directory is the common case: one path, conventional names, no remembering
119
+ // which extension goes with which renderer. A named file still wins.
120
+ const dir = pick(argv.out, 'outputs.dir', config.outputs?.dir);
121
+ const inDir = (name) => dir && path.join(dir, name);
122
+ return {
123
+ pgpm: pick(argv.pgpm, 'source.pgpm', config.source?.pgpm),
124
+ // An explicit connection on the command line beats a configured source:
125
+ // pointing the same config at a database you already have is the whole
126
+ // reason to type one, and deploying a throwaway copy instead would ignore it.
127
+ usePgpm: argv.pgpm !== undefined || (config.source?.pgpm !== undefined && !hasConnectionFlag(argv)),
128
+ perfBaseline: pick(argv['perf-baseline'], 'perf.baseline', config.perf?.baseline),
129
+ callGraphBaseline: pick(argv.baseline, 'callGraph.baseline', config.callGraph?.baseline),
130
+ outputs: {
131
+ json: pick(argv['write-json'], 'outputs.json', config.outputs?.json) ?? inDir('safegres.json'),
132
+ markdown: pick(argv['write-markdown'], 'outputs.markdown', config.outputs?.markdown)
133
+ ?? inDir('safegres.md'),
134
+ sarif: pick(argv['write-sarif'], 'outputs.sarif', config.outputs?.sarif) ?? inDir('safegres.sarif'),
135
+ sarifSources: pick(argv['sarif-sources'], 'outputs.sarifSources', config.outputs?.sarifSources),
136
+ snapshot: pick(argv['write-snapshot'], 'outputs.snapshot', config.outputs?.snapshot),
137
+ githubComment: pick(argv['write-github-comment'], 'outputs.githubComment', config.outputs?.githubComment)
138
+ }
139
+ };
140
+ }
141
+ /** Build config-loading params from shared CLI flags. */
142
+ function configParamsFromArgv(argv) {
143
+ const cliRules = parseRuleFlags(argv.rule);
144
+ const overrides = {};
145
+ if (cliRules)
146
+ overrides.rules = cliRules;
147
+ return {
148
+ configFile: typeof argv.config === 'string' ? argv.config : undefined,
149
+ preset: typeof argv.preset === 'string' ? argv.preset : undefined,
150
+ overrides: Object.keys(overrides).length > 0 ? overrides : undefined,
151
+ sealed: argv.sealed === true
152
+ };
153
+ }
package/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/cli.js ADDED
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const logger_1 = require("@pgpmjs/logger");
5
+ const inquirerer_1 = require("inquirerer");
6
+ const commands_1 = require("./cli/commands");
7
+ const log = new logger_1.Logger('safegres');
8
+ if (process.argv.includes('--version') || process.argv.includes('-v')) {
9
+ const pkg = (0, inquirerer_1.getPackageJson)(__dirname);
10
+ process.stdout.write(`${pkg.version}\n`);
11
+ process.exit(0);
12
+ }
13
+ const options = {
14
+ minimistOpts: {
15
+ alias: { v: 'version', h: 'help', q: 'summary' },
16
+ boolean: [
17
+ 'skip-ast',
18
+ 'color',
19
+ 'help',
20
+ 'version',
21
+ 'summary',
22
+ 'verbose',
23
+ 'call-graph',
24
+ 'fail-on-new-boundaries',
25
+ 'keep',
26
+ 'list',
27
+ 'json'
28
+ ],
29
+ string: [
30
+ 'baseline',
31
+ 'write-baseline',
32
+ 'compare',
33
+ 'compare-ref',
34
+ 'compare-sha',
35
+ 'compare-run-id',
36
+ 'compare-run-url',
37
+ 'compare-age',
38
+ 'compare-skipped',
39
+ 'write-snapshot',
40
+ 'connection',
41
+ 'host',
42
+ 'user',
43
+ 'password',
44
+ 'database',
45
+ 'schemas',
46
+ 'exclude-schemas',
47
+ 'ignore-extensions',
48
+ 'roles',
49
+ 'exclude-roles',
50
+ 'format',
51
+ 'fail-on',
52
+ 'out',
53
+ 'preset',
54
+ 'corpus',
55
+ 'case',
56
+ 'provider',
57
+ 'repo',
58
+ 'base',
59
+ 'head',
60
+ 'workflow',
61
+ 'artifact',
62
+ 'dir'
63
+ ]
64
+ }
65
+ };
66
+ new inquirerer_1.CLI(commands_1.commands, options).run().catch((error) => {
67
+ log.error(error);
68
+ process.exit(1);
69
+ });