@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,355 @@
1
+ "use strict";
2
+ /**
3
+ * Markdown rendering (`--format markdown`), for the places CI reads a report:
4
+ * a GitHub job summary (`$GITHUB_STEP_SUMMARY`) or a PR comment.
5
+ *
6
+ * The pretty renderer is a terminal artifact — ANSI colors, fixed-width
7
+ * severity labels, a long scrollable list. A PR comment is read once, by
8
+ * someone deciding whether to look further, so this renders the same report
9
+ * as tables: scores first, then findings grouped by rule, with the noisy
10
+ * parts (internal advisories, accepted debt) collapsed into `<details>`.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.renderMarkdown = renderMarkdown;
14
+ const compare_1 = require("./compare");
15
+ const view_1 = require("./view");
16
+ const SEV_ICON = {
17
+ critical: '🔴',
18
+ high: '🟠',
19
+ medium: '🟡',
20
+ low: '🔵',
21
+ info: '⚪'
22
+ };
23
+ /**
24
+ * Movement, colored by whether it is good news — the severity icons already
25
+ * spend red on "this is serious", so a delta that reuses red for "+15 info
26
+ * findings" reads as a fire when nothing is burning. Green is fewer findings /
27
+ * a higher score, red is the reverse, grey is neither.
28
+ */
29
+ function movement(delta, betterWhen, digits = 0) {
30
+ if (delta === 0)
31
+ return `⚪ ${(0, compare_1.formatDelta)(0)}`;
32
+ const improved = betterWhen === 'lower' ? delta < 0 : delta > 0;
33
+ const arrow = delta > 0 ? '▲' : '▼';
34
+ return `${improved ? '🟢' : '🔴'} ${arrow} ${(0, compare_1.formatDelta)(delta, digits)}`;
35
+ }
36
+ function renderMarkdown(report, options = {}) {
37
+ const view = (0, view_1.selectView)(report, {
38
+ detail: options.summary ? 'summary' : options.verbose ? 'verbose' : 'normal',
39
+ ...(options.planes ? { planes: options.planes } : {}),
40
+ ...options.view
41
+ });
42
+ const out = [`## ${options.title ?? 'safegres'}`, ''];
43
+ out.push(...scoreTable(report, options), '');
44
+ if (report.exposure) {
45
+ const { known, source, exposedTables, totalTables, roles, unaddressable } = report.exposure;
46
+ out.push(known
47
+ ? `Exposure (${source}): **${exposedTables}/${totalTables}** tables reachable`
48
+ + `${roles && roles.length > 0 ? ` via \`${roles.join('`, `')}\`` : ''}.`
49
+ + (unaddressable && unaddressable.length > 0
50
+ ? ` ${unaddressable.length} relation(s) in those schemas are declared unaddressable`
51
+ + ` by the API: ${unaddressable.map((r) => `\`${r.schema}.${r.table}\``).join(', ')}.`
52
+ : '')
53
+ : '> [!WARNING]\n> Exposure unknown — the entire database is assumed reachable and the score is capped.', '');
54
+ }
55
+ if (view.has('scorecards'))
56
+ out.push(...scorecardSection(view), '');
57
+ if (view.has('planes'))
58
+ out.push(...planeSection(view), '');
59
+ out.push(countsTable(report), '');
60
+ if (report.comparison)
61
+ out.push(...comparisonSection(report.comparison), '');
62
+ else if (report.comparisonSkipped)
63
+ out.push(...noBaselineSection(report.comparisonSkipped), '');
64
+ if (view.detail === 'summary') {
65
+ // The ratchet's verdict is the one perf number a summary reader needs:
66
+ // the absolute score is dominated by accepted debt, the delta is not.
67
+ const diff = report.perf?.diff;
68
+ if (diff) {
69
+ out.push(`Perf baseline: **${diff.added.length} new**, ${diff.accepted.length} accepted, `
70
+ + `${diff.removed.length} resolved.`, '');
71
+ }
72
+ return out.join('\n');
73
+ }
74
+ out.push(...findingSection('Security findings', [...view.security.exposed, ...view.security.internal], options), '');
75
+ if (report.roleAccess && report.roleAccess.roles.length > 0) {
76
+ out.push(...roleAccessSection(report.roleAccess.roles), '');
77
+ }
78
+ if (report.perf) {
79
+ out.push(...findingSection('Performance findings', report.perf.findings, options));
80
+ const { paths, stats, explain, diff } = report.perf;
81
+ const notes = [];
82
+ if (paths && paths.writeOnceShaped > 0) {
83
+ const acted = {
84
+ report: 'X1 still asks for an index on each of them',
85
+ demote: 'their X1 findings are demoted to `info`',
86
+ suppress: 'their X1 findings are suppressed'
87
+ }[paths.onWriteOncePointer];
88
+ notes.push(`Access paths: of ${paths.total} foreign keys, ${paths.read} are named by an RLS policy `
89
+ + `or a view, and ${paths.writeOnceShaped} across ${paths.tables} tables look like `
90
+ + `write-once provisioning pointers — ${acted}. A shape is not proof that nothing `
91
+ + 'queries the relation (`perf.paths.onWriteOncePointer` to change what X1 does).');
92
+ }
93
+ if (stats) {
94
+ notes.push(`Runtime statistics: ${stats.tables} tables, counters since ${stats.statsReset ?? 'server start'}`
95
+ + `${stats.scored ? '' : ' (advisory — `includeStats` is false)'}.`);
96
+ for (const note of stats.notes ?? [])
97
+ notes.push(note);
98
+ }
99
+ if (explain) {
100
+ notes.push(explain.unavailable
101
+ ?? `Planner proof: ${explain.confirmed} confirmed, ${explain.refuted} refuted, `
102
+ + `${explain.inconclusive} inconclusive of ${explain.probed} probed.`);
103
+ }
104
+ if (notes.length > 0)
105
+ out.push('', notes.map((n) => `_${n}_`).join(' \n'));
106
+ if (diff) {
107
+ out.push('', '### Performance vs baseline', '');
108
+ out.push(diff.added.length === 0
109
+ ? `No new perf debt (${diff.accepted.length} accepted, ${diff.removed.length} fixed).`
110
+ : `**${diff.added.length} new** since the baseline `
111
+ + `(${diff.accepted.length} accepted, ${diff.removed.length} fixed):`);
112
+ if (diff.added.length > 0)
113
+ out.push('', findingTable(diff.added));
114
+ }
115
+ out.push('');
116
+ }
117
+ return out.join('\n');
118
+ }
119
+ /**
120
+ * The other ways in, as one table. Secondary planes are advisory by
121
+ * construction — an internal role reaching internal tables is the schema
122
+ * working as designed — so they read as context under the headline rather
123
+ * than as a second verdict competing with it.
124
+ */
125
+ /**
126
+ * The other named scores. Same findings, different questions — which is the
127
+ * point: a team that gates on `anon-surface` is not being asked to care
128
+ * about the headline, and `raw` is there so nobody has to trust that the
129
+ * config was written in good faith.
130
+ */
131
+ function scorecardSection(view) {
132
+ const out = [
133
+ '### Scorecards',
134
+ '',
135
+ '_The same findings, scored by question. Nothing here filters the report — '
136
+ + 'a scorecard decides what a number is *about*, never what is reported._',
137
+ '',
138
+ '| Scorecard | Score | Grade | Findings | Question |',
139
+ '| --- | ---: | --- | ---: | --- |'
140
+ ];
141
+ for (const card of view.scorecards) {
142
+ out.push(`| \`${card.name}\` | ${card.score.value} | **${card.score.grade}** | ${card.findings} `
143
+ + `| ${card.description ?? card.title ?? ''} |`);
144
+ }
145
+ return out;
146
+ }
147
+ function planeSection(view) {
148
+ const out = [
149
+ '### Other access planes',
150
+ '',
151
+ '_Advisory: these are not the score above. The headline grades the declared API surface; '
152
+ + 'a plane grades what somebody reaches without going through it._',
153
+ '',
154
+ '| Plane | Kind | Reaches | Relations | Score | Grade |',
155
+ '| --- | --- | --- | ---: | ---: | --- |'
156
+ ];
157
+ for (const plane of view.planes)
158
+ out.push(planeRow(plane));
159
+ for (const plane of view.expandedPlanes) {
160
+ if (plane.skipped || plane.score.deductions.length === 0)
161
+ continue;
162
+ out.push('', `#### Plane \`${plane.name}\` by rule`, '', '| Rule | Findings | Points | Grade | Payoff |', '| --- | ---: | ---: | --- | ---: |', ...plane.score.deductions.map(deductionRow));
163
+ }
164
+ return out;
165
+ }
166
+ function planeRow(plane) {
167
+ const who = plane.roles && plane.roles.length > 0
168
+ ? plane.roles.map((r) => `\`${r}\``).join(', ')
169
+ : plane.schemas.map((s) => `\`${s}\``).join(', ') || '—';
170
+ if (plane.skipped) {
171
+ return `| \`${plane.name}\` | ${plane.kind} | ${who} | — | — | not graded — ${plane.skipped} |`;
172
+ }
173
+ const via = plane.reachedVia ? ` (via ${plane.reachedVia})` : '';
174
+ return `| \`${plane.name}\` | ${plane.kind} | ${who}${via} | ${plane.exposedTables} `
175
+ + `| **${plane.score.value}** | **${plane.score.grade}** |`;
176
+ }
177
+ /**
178
+ * The direct answer to "what can role X access?" — effective grants
179
+ * (direct, TO PUBLIC, inherited), classified by whether RLS mediates them.
180
+ */
181
+ function roleAccessSection(roles) {
182
+ const out = ['### Role access', ''];
183
+ for (const entry of roles) {
184
+ out.push(`\`${entry.role}\`: **${entry.accessibleTables}** relation(s) accessible — `
185
+ + `${entry.unmediated.length} unmediated (no RLS), ${entry.mediated} policy-mediated`
186
+ + `${entry.dead > 0 ? `, ${entry.dead} dead (RLS default-deny)` : ''}.`, '');
187
+ if (entry.unmediated.length > 0) {
188
+ out.push('| Relation | Privileges | Via |', '| --- | --- | --- |', ...entry.unmediated.map((r) => `| \`${r.schema}.${r.table}\` | ${r.privileges.join(', ')}`
189
+ + `${r.columns ? ` (${r.columns.join(', ')})` : ''} | ${r.via} |`), '');
190
+ }
191
+ }
192
+ return out;
193
+ }
194
+ function scoreTable(report, options) {
195
+ const cmp = report.comparison;
196
+ const rows = [];
197
+ if (report.score)
198
+ rows.push(scoreRow('Security', report.score, !!cmp, cmp?.security));
199
+ if (report.perf)
200
+ rows.push(scoreRow('Performance', report.perf.score, !!cmp, cmp?.perf));
201
+ if (rows.length === 0)
202
+ return [];
203
+ const deltaHeader = cmp ? ` Δ vs ${cmp.previous.ref ?? 'previous run'} |` : '';
204
+ return [
205
+ `| Dimension | Score | Grade |${deltaHeader} Top deductions |`,
206
+ `| --- | --- | --- |${cmp ? ' --- |' : ''} --- |`,
207
+ ...rows,
208
+ '',
209
+ ...ruleTable('Security', report.score, options),
210
+ ...ruleTable('Performance', report.perf?.score, options)
211
+ ];
212
+ }
213
+ function scoreRow(label, score, compared, delta) {
214
+ const top = score.deductions
215
+ .filter((d) => !d.unscored)
216
+ .slice(0, 3)
217
+ .map((d) => `\`${d.code}\` −${d.points} (×${d.count})`)
218
+ .join(', ');
219
+ const capped = score.cappedByUnknownExposure ? ' (capped)' : '';
220
+ // The column exists for the whole table or not at all: a dimension the
221
+ // previous run didn't have still needs its cell.
222
+ const deltaCell = compared ? ` ${delta ? scoreDeltaCell(delta) : '— (new)'} |` : '';
223
+ return `| ${label} | **${score.value}**${capped} | **${score.grade}** |${deltaCell} ${top || '—'} |`;
224
+ }
225
+ /**
226
+ * The movement, made legible at a glance: an arrow for the direction, the
227
+ * grade transition when it crossed a band, and the finding count either way —
228
+ * a score can hold still while findings move underneath it.
229
+ */
230
+ function scoreDeltaCell(d) {
231
+ const score = d.delta === 0 ? '⚪ no change' : `${movement(d.delta, 'higher', 1)} (from ${d.before})`;
232
+ const grade = d.gradeBefore === d.gradeAfter ? '' : ` · ${d.gradeBefore} → ${d.gradeAfter}`;
233
+ const findings = d.findingsAfter === d.findingsBefore
234
+ ? ''
235
+ : ` · ${d.findingsBefore} → ${d.findingsAfter} findings `
236
+ + `${movement(d.findingsAfter - d.findingsBefore, 'lower')}`;
237
+ return `${score}${grade}${findings}`;
238
+ }
239
+ /**
240
+ * A rule with no previous reading is not movement: the previous run simply did
241
+ * not report the code (a rule added since, or a dimension it never ran).
242
+ */
243
+ function ruleDeltaCell(r) {
244
+ return r.unmeasuredBefore ? '⚪ not measured before' : movement(r.delta, 'lower');
245
+ }
246
+ /**
247
+ * Rendered after the counts so the two tables can be read together: what the
248
+ * numbers are, then which way they moved.
249
+ */
250
+ function comparisonSection(cmp) {
251
+ const since = (0, compare_1.describeBaseline)(cmp.previous);
252
+ if (cmp.unchanged)
253
+ return ['', `_No change since ${since}._`];
254
+ const out = [
255
+ '',
256
+ `<details open><summary>Changes since ${since}</summary>`,
257
+ '',
258
+ '🟢 improvement · 🔴 regression · ⚪ no change or no previous reading',
259
+ ''
260
+ ];
261
+ const severities = ['critical', 'high', 'medium', 'low', 'info'];
262
+ const moved = severities.filter((sev) => cmp.summary[sev].delta !== 0);
263
+ if (moved.length > 0) {
264
+ out.push(`| ${moved.map((sev) => `${SEV_ICON[sev]} ${sev}`).join(' | ')} |`, `| ${moved.map(() => '---').join(' | ')} |`, `| ${moved
265
+ .map((sev) => {
266
+ const s = cmp.summary[sev];
267
+ return `${s.before} → **${s.after}** ${movement(s.delta, 'lower')}`;
268
+ })
269
+ .join(' | ')} |`, '');
270
+ }
271
+ if (cmp.rules.length > 0) {
272
+ out.push('| Rule | Dimension | Before | After | Δ |', '| --- | --- | ---: | ---: | --- |', ...cmp.rules.map((r) => `| \`${r.code}\` | ${r.dimension} | ${r.unmeasuredBefore ? '—' : r.before} | `
273
+ + `${r.after} | ${ruleDeltaCell(r)} |`), '');
274
+ }
275
+ out.push('</details>');
276
+ return out;
277
+ }
278
+ /**
279
+ * A delta was asked for and none was trustworthy. Said out loud, because an
280
+ * absent delta is indistinguishable from "nothing changed" — and because the
281
+ * gates that do not read the comparison are still in force.
282
+ */
283
+ function noBaselineSection(reason) {
284
+ return [
285
+ '',
286
+ `> [!NOTE]`,
287
+ `> No delta baseline: ${reason}. The absolute score and the perf baseline still gate this run.`
288
+ ];
289
+ }
290
+ /**
291
+ * Per-rule breakdown. `Payoff` is what the dimension score becomes if that
292
+ * rule alone goes to zero — the number worth ranking work by, and not
293
+ * proportional to the finding count, because the curve is exponential.
294
+ */
295
+ /**
296
+ * One rule's row. Findings and fixes are different numbers when a rule fans
297
+ * out over a single repair, and points are charged on the second.
298
+ */
299
+ function deductionRow(d) {
300
+ const found = d.units === undefined ? `${d.count}` : `${d.count} (${d.units} fixes)`;
301
+ const points = d.capped ? `−${d.points} (capped)` : `−${d.points}`;
302
+ return d.unscored
303
+ ? `| \`${d.code}\` | ${found} | — | — | *unscored* |`
304
+ : `| \`${d.code}\` | ${found} | ${points} | **${d.grade}** | +${d.potential.toFixed(1)} |`;
305
+ }
306
+ function ruleTable(label, score, options) {
307
+ if (!score || score.deductions.length === 0)
308
+ return [];
309
+ const table = [
310
+ '| Rule | Findings | Points | Grade | Payoff |',
311
+ '| --- | ---: | ---: | --- | ---: |',
312
+ ...score.deductions.map(deductionRow)
313
+ ];
314
+ return options.verbose
315
+ ? [`### ${label} by rule`, '', ...table, '']
316
+ : [`<details><summary>${label} by rule</summary>`, '', ...table, '', '</details>', ''];
317
+ }
318
+ function countsTable(report) {
319
+ const s = report.summary;
320
+ return [
321
+ '| 🔴 critical | 🟠 high | 🟡 medium | 🔵 low | ⚪ info |',
322
+ '| --- | --- | --- | --- | --- |',
323
+ `| ${s.critical} | ${s.high} | ${s.medium} | ${s.low} | ${s.info} |`
324
+ ].join('\n');
325
+ }
326
+ function findingSection(heading, findings, options) {
327
+ const out = [`### ${heading}`, ''];
328
+ const exposed = findings.filter((f) => f.exposed !== false);
329
+ const internal = findings.filter((f) => f.exposed === false);
330
+ if (exposed.length === 0)
331
+ out.push('No findings.');
332
+ else
333
+ out.push(findingTable(exposed));
334
+ if (internal.length > 0) {
335
+ const table = findingTable(internal);
336
+ out.push('', options.verbose
337
+ ? table
338
+ : `<details><summary>${internal.length} internal `
339
+ + `advisor${internal.length === 1 ? 'y' : 'ies'} — not exposed via any API, `
340
+ + `excluded from the score</summary>\n\n${table}\n\n</details>`);
341
+ }
342
+ return out;
343
+ }
344
+ function findingTable(findings) {
345
+ const rows = findings.map((f) => {
346
+ const where = [f.schema, f.table].filter(Boolean).join('.') || '—';
347
+ const policy = f.policy ? ` \`${f.policy}\`` : '';
348
+ return `| ${SEV_ICON[f.severity]} ${f.severity} | \`${f.code}\` | ${where}${policy} | ${escapeCell(f.message)} |`;
349
+ });
350
+ return ['| Severity | Rule | Relation | Finding |', '| --- | --- | --- | --- |', ...rows].join('\n');
351
+ }
352
+ /** Keep a message inside its table cell: no pipes, no line breaks. */
353
+ function escapeCell(value) {
354
+ return value.replace(/\|/g, '\\|').replace(/\s*\n\s*/g, ' ');
355
+ }
@@ -0,0 +1,14 @@
1
+ import type { Report } from '../types';
2
+ import { type ViewConfig } from './view';
3
+ export interface RenderPrettyOptions {
4
+ color?: boolean;
5
+ /** Only render the exposure line, score, and severity summary — no per-finding lines. */
6
+ summary?: boolean;
7
+ /** Expand the internal (non-exposed) advisories instead of collapsing them to a count. */
8
+ verbose?: boolean;
9
+ /** Secondary planes to expand, by name or glob. Default: summarized in one line each. */
10
+ planes?: string[];
11
+ /** Everything else the view layer selects. Beats the flags above. */
12
+ view?: ViewConfig;
13
+ }
14
+ export declare function renderPretty(report: Report, options?: RenderPrettyOptions): string;