@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
package/index.js CHANGED
@@ -1,4 +1,11 @@
1
1
  "use strict";
2
+ /**
3
+ * Public surface of `safegres` — a pure-PostgreSQL Row-Level-Security auditor.
4
+ *
5
+ * The auditor introspects pg_class / pg_policy / role grants and emits
6
+ * structured findings (A1–A7, P1, P5). It has no knowledge of any specific
7
+ * application schema or policy DSL.
8
+ */
2
9
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
10
  if (k2 === undefined) k2 = k;
4
11
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -14,9 +21,225 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
21
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
22
  };
16
23
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./admin"), exports);
18
- __exportStar(require("./connect"), exports);
19
- __exportStar(require("./manager"), exports);
20
- __exportStar(require("./roles"), exports);
21
- __exportStar(require("./seed"), exports);
22
- __exportStar(require("./test-client"), exports);
24
+ exports.analyzeViewWrites = exports.checkMatviewSnapshot = exports.checkLeakyFilterView = exports.analyzeViewExposure = exports.DEFAULT_STATS_THRESHOLDS = exports.checkUnusedIndexes = exports.checkTopStatements = exports.checkStats = exports.checkSeqScanDominant = exports.checkDeadTuples = exports.checkUntrustedRoleWrites = exports.checkUntrustedRolePolicies = exports.checkPublicGrants = exports.collectPredicateColumns = exports.checkUnindexedPolicyColumns = exports.checkUnhoistedPolicyFunctions = exports.checkPolicyColumnCasts = exports.checkNonLeakproofPolicyFunctions = exports.checkUntrustedSequenceGrants = exports.checkUntrustedForeignTableGrants = exports.effectiveGrants = exports.effectiveColumnGrants = exports.computeRoleAccess = exports.checkUntrustedIndirectAccess = exports.checkUnreachableGrants = exports.checkIndirectCoverageGaps = exports.checkDeadSchemaUsage = exports.checkDeadPolicies = exports.checkUnindexedSortColumns = exports.checkUnindexedSearchColumns = exports.checkUnindexedForeignKeys = exports.checkRedundantIndexes = exports.checkMissingPrimaryKey = exports.checkUnreadableViewReach = exports.checkUnauditedViewReach = exports.checkDefinerViewBypass = exports.analyzeViewBodies = exports.checkUnreadableFunctionReach = exports.checkInsteadOfTriggerWrite = exports.checkDefinerFunctionReach = exports.analyzeFunctionBodies = exports.checkUntrustedColumnGrants = exports.buildCallGraph = exports.toBaseline = exports.serializeBaseline = exports.parseBaseline = exports.diffCallGraph = exports.boundaryKey = exports.PolicyParseError = exports.parsePolicyExpression = void 0;
25
+ exports.supabaseAdapter = exports.resolveAdapters = exports.postgrestAdapter = exports.postgraphileAdapter = exports.hasuraAdapter = exports.graphileAdapter = exports.definePlanes = exports.constructiveAdapter = exports.BUILTIN_ADAPTERS = exports.loadCorpus = exports.loadCase = exports.gradeCase = exports.corpusDir = exports.corpusBootstrap = exports.validateConfigShape = exports.toJsonSchema = exports.SCHEMA_ID = exports.CONFIG_SHAPE = exports.rulesForTable = exports.ruleCodesForDimension = exports.resolveRules = exports.matchTablePattern = exports.defaultRuleMap = exports.ConfigValidationError = exports.applyRulesToFindings = exports.allAstRulesDisabled = exports.supabase = exports.strict = exports.recommended = exports.PRESETS = exports.postgrest = exports.oltp = exports.multiTenant = exports.minimal = exports.hasura = exports.graphile = exports.constructive = exports.safegresConfigLoader = exports.loadConfig = exports.configFingerprint = exports.runEval = exports.doctor = exports.audit = exports.selectGithubBaseline = exports.selectBaseline = exports.MAX_BASELINE_AGE_MS = exports.CANDIDATE_LIMIT = exports.checkViewRuleBypass = exports.checkUncheckedViewWrite = exports.checkDefinerViewWrite = void 0;
26
+ exports.scoreBadge = exports.renderGithubSummary = exports.renderGithubComment = exports.renderAnnotations = exports.postStickyComment = exports.gradeBadge = exports.emitGithub = exports.COMMENT_MARKER = exports.toSnapshot = exports.serializeSnapshot = exports.parseSnapshot = exports.formatDelta = exports.formatAge = exports.describeBaseline = exports.compareReports = exports.baselineLabel = exports.renderCallGraphDiff = exports.renderCallGraph = exports.introspectStats = exports.resolveRoles = exports.listAuditableRoles = exports.introspectObjectAcls = exports.introspectTables = exports.introspectViews = exports.introspectIndexes = exports.introspectFunctions = exports.UNKNOWN_EXPOSURE = exports.resolveReach = exports.resolvePlanes = exports.resolveExposure = exports.resolveConstructiveExposure = exports.introspectSchemaAcls = exports.introspectRoleGraph = exports.proveFindings = exports.toPerfBaseline = exports.toBaselineFinding = exports.subjectOf = exports.serializePerfBaseline = exports.parsePerfBaseline = exports.findingKey = exports.diffPerf = exports.ROOT_ABILITIES = exports.FORWARD_ABILITIES = exports.computeApiReach = exports.BACKWARD_ABILITIES = exports.stampPlanes = exports.scorePlane = exports.resolvePlaneReach = exports.relationKey = exports.onPlane = void 0;
27
+ exports.meetsGrade = exports.DEFAULT_WEIGHTS = exports.DEFAULT_GRADE_BANDS = exports.computeScore = exports.RULES_BY_CODE = exports.RULES = exports.isKnownRule = exports.expandRuleSelector = exports.dimensionOf = exports.viewConfigFromReportConfig = exports.selectView = exports.matchPlane = exports.ALL_SECTIONS = exports.renderSarif = exports.buildSourceIndex = exports.renderPretty = exports.renderMarkdown = exports.renderJson = void 0;
28
+ var parse_1 = require("./ast/parse");
29
+ Object.defineProperty(exports, "parsePolicyExpression", { enumerable: true, get: function () { return parse_1.parsePolicyExpression; } });
30
+ Object.defineProperty(exports, "PolicyParseError", { enumerable: true, get: function () { return parse_1.PolicyParseError; } });
31
+ var baseline_1 = require("./callgraph/baseline");
32
+ Object.defineProperty(exports, "boundaryKey", { enumerable: true, get: function () { return baseline_1.boundaryKey; } });
33
+ Object.defineProperty(exports, "diffCallGraph", { enumerable: true, get: function () { return baseline_1.diffCallGraph; } });
34
+ Object.defineProperty(exports, "parseBaseline", { enumerable: true, get: function () { return baseline_1.parseBaseline; } });
35
+ Object.defineProperty(exports, "serializeBaseline", { enumerable: true, get: function () { return baseline_1.serializeBaseline; } });
36
+ Object.defineProperty(exports, "toBaseline", { enumerable: true, get: function () { return baseline_1.toBaseline; } });
37
+ var graph_1 = require("./callgraph/graph");
38
+ Object.defineProperty(exports, "buildCallGraph", { enumerable: true, get: function () { return graph_1.buildCallGraph; } });
39
+ var column_grants_1 = require("./checks/column-grants");
40
+ Object.defineProperty(exports, "checkUntrustedColumnGrants", { enumerable: true, get: function () { return column_grants_1.checkUntrustedColumnGrants; } });
41
+ var definer_function_1 = require("./checks/definer-function");
42
+ Object.defineProperty(exports, "analyzeFunctionBodies", { enumerable: true, get: function () { return definer_function_1.analyzeFunctionBodies; } });
43
+ Object.defineProperty(exports, "checkDefinerFunctionReach", { enumerable: true, get: function () { return definer_function_1.checkDefinerFunctionReach; } });
44
+ Object.defineProperty(exports, "checkInsteadOfTriggerWrite", { enumerable: true, get: function () { return definer_function_1.checkInsteadOfTriggerWrite; } });
45
+ Object.defineProperty(exports, "checkUnreadableFunctionReach", { enumerable: true, get: function () { return definer_function_1.checkUnreadableFunctionReach; } });
46
+ var definer_view_1 = require("./checks/definer-view");
47
+ Object.defineProperty(exports, "analyzeViewBodies", { enumerable: true, get: function () { return definer_view_1.analyzeViewBodies; } });
48
+ Object.defineProperty(exports, "checkDefinerViewBypass", { enumerable: true, get: function () { return definer_view_1.checkDefinerViewBypass; } });
49
+ Object.defineProperty(exports, "checkUnauditedViewReach", { enumerable: true, get: function () { return definer_view_1.checkUnauditedViewReach; } });
50
+ Object.defineProperty(exports, "checkUnreadableViewReach", { enumerable: true, get: function () { return definer_view_1.checkUnreadableViewReach; } });
51
+ var indexes_1 = require("./checks/indexes");
52
+ Object.defineProperty(exports, "checkMissingPrimaryKey", { enumerable: true, get: function () { return indexes_1.checkMissingPrimaryKey; } });
53
+ Object.defineProperty(exports, "checkRedundantIndexes", { enumerable: true, get: function () { return indexes_1.checkRedundantIndexes; } });
54
+ Object.defineProperty(exports, "checkUnindexedForeignKeys", { enumerable: true, get: function () { return indexes_1.checkUnindexedForeignKeys; } });
55
+ Object.defineProperty(exports, "checkUnindexedSearchColumns", { enumerable: true, get: function () { return indexes_1.checkUnindexedSearchColumns; } });
56
+ Object.defineProperty(exports, "checkUnindexedSortColumns", { enumerable: true, get: function () { return indexes_1.checkUnindexedSortColumns; } });
57
+ var lattice_1 = require("./checks/lattice");
58
+ Object.defineProperty(exports, "checkDeadPolicies", { enumerable: true, get: function () { return lattice_1.checkDeadPolicies; } });
59
+ Object.defineProperty(exports, "checkDeadSchemaUsage", { enumerable: true, get: function () { return lattice_1.checkDeadSchemaUsage; } });
60
+ Object.defineProperty(exports, "checkIndirectCoverageGaps", { enumerable: true, get: function () { return lattice_1.checkIndirectCoverageGaps; } });
61
+ Object.defineProperty(exports, "checkUnreachableGrants", { enumerable: true, get: function () { return lattice_1.checkUnreachableGrants; } });
62
+ Object.defineProperty(exports, "checkUntrustedIndirectAccess", { enumerable: true, get: function () { return lattice_1.checkUntrustedIndirectAccess; } });
63
+ Object.defineProperty(exports, "computeRoleAccess", { enumerable: true, get: function () { return lattice_1.computeRoleAccess; } });
64
+ Object.defineProperty(exports, "effectiveColumnGrants", { enumerable: true, get: function () { return lattice_1.effectiveColumnGrants; } });
65
+ Object.defineProperty(exports, "effectiveGrants", { enumerable: true, get: function () { return lattice_1.effectiveGrants; } });
66
+ var object_acls_1 = require("./checks/object-acls");
67
+ Object.defineProperty(exports, "checkUntrustedForeignTableGrants", { enumerable: true, get: function () { return object_acls_1.checkUntrustedForeignTableGrants; } });
68
+ Object.defineProperty(exports, "checkUntrustedSequenceGrants", { enumerable: true, get: function () { return object_acls_1.checkUntrustedSequenceGrants; } });
69
+ var policy_index_1 = require("./checks/policy-index");
70
+ Object.defineProperty(exports, "checkNonLeakproofPolicyFunctions", { enumerable: true, get: function () { return policy_index_1.checkNonLeakproofPolicyFunctions; } });
71
+ Object.defineProperty(exports, "checkPolicyColumnCasts", { enumerable: true, get: function () { return policy_index_1.checkPolicyColumnCasts; } });
72
+ Object.defineProperty(exports, "checkUnhoistedPolicyFunctions", { enumerable: true, get: function () { return policy_index_1.checkUnhoistedPolicyFunctions; } });
73
+ Object.defineProperty(exports, "checkUnindexedPolicyColumns", { enumerable: true, get: function () { return policy_index_1.checkUnindexedPolicyColumns; } });
74
+ Object.defineProperty(exports, "collectPredicateColumns", { enumerable: true, get: function () { return policy_index_1.collectPredicateColumns; } });
75
+ var role_trust_1 = require("./checks/role-trust");
76
+ Object.defineProperty(exports, "checkPublicGrants", { enumerable: true, get: function () { return role_trust_1.checkPublicGrants; } });
77
+ Object.defineProperty(exports, "checkUntrustedRolePolicies", { enumerable: true, get: function () { return role_trust_1.checkUntrustedRolePolicies; } });
78
+ Object.defineProperty(exports, "checkUntrustedRoleWrites", { enumerable: true, get: function () { return role_trust_1.checkUntrustedRoleWrites; } });
79
+ var stats_1 = require("./checks/stats");
80
+ Object.defineProperty(exports, "checkDeadTuples", { enumerable: true, get: function () { return stats_1.checkDeadTuples; } });
81
+ Object.defineProperty(exports, "checkSeqScanDominant", { enumerable: true, get: function () { return stats_1.checkSeqScanDominant; } });
82
+ Object.defineProperty(exports, "checkStats", { enumerable: true, get: function () { return stats_1.checkStats; } });
83
+ Object.defineProperty(exports, "checkTopStatements", { enumerable: true, get: function () { return stats_1.checkTopStatements; } });
84
+ Object.defineProperty(exports, "checkUnusedIndexes", { enumerable: true, get: function () { return stats_1.checkUnusedIndexes; } });
85
+ Object.defineProperty(exports, "DEFAULT_STATS_THRESHOLDS", { enumerable: true, get: function () { return stats_1.DEFAULT_STATS_THRESHOLDS; } });
86
+ var view_exposure_1 = require("./checks/view-exposure");
87
+ Object.defineProperty(exports, "analyzeViewExposure", { enumerable: true, get: function () { return view_exposure_1.analyzeViewExposure; } });
88
+ Object.defineProperty(exports, "checkLeakyFilterView", { enumerable: true, get: function () { return view_exposure_1.checkLeakyFilterView; } });
89
+ Object.defineProperty(exports, "checkMatviewSnapshot", { enumerable: true, get: function () { return view_exposure_1.checkMatviewSnapshot; } });
90
+ var view_writes_1 = require("./checks/view-writes");
91
+ Object.defineProperty(exports, "analyzeViewWrites", { enumerable: true, get: function () { return view_writes_1.analyzeViewWrites; } });
92
+ Object.defineProperty(exports, "checkDefinerViewWrite", { enumerable: true, get: function () { return view_writes_1.checkDefinerViewWrite; } });
93
+ Object.defineProperty(exports, "checkUncheckedViewWrite", { enumerable: true, get: function () { return view_writes_1.checkUncheckedViewWrite; } });
94
+ Object.defineProperty(exports, "checkViewRuleBypass", { enumerable: true, get: function () { return view_writes_1.checkViewRuleBypass; } });
95
+ var baseline_2 = require("./ci/baseline");
96
+ Object.defineProperty(exports, "CANDIDATE_LIMIT", { enumerable: true, get: function () { return baseline_2.CANDIDATE_LIMIT; } });
97
+ Object.defineProperty(exports, "MAX_BASELINE_AGE_MS", { enumerable: true, get: function () { return baseline_2.MAX_BASELINE_AGE_MS; } });
98
+ Object.defineProperty(exports, "selectBaseline", { enumerable: true, get: function () { return baseline_2.selectBaseline; } });
99
+ var github_1 = require("./ci/github");
100
+ Object.defineProperty(exports, "selectGithubBaseline", { enumerable: true, get: function () { return github_1.selectGithubBaseline; } });
101
+ var audit_1 = require("./commands/audit");
102
+ Object.defineProperty(exports, "audit", { enumerable: true, get: function () { return audit_1.audit; } });
103
+ var doctor_1 = require("./commands/doctor");
104
+ Object.defineProperty(exports, "doctor", { enumerable: true, get: function () { return doctor_1.doctor; } });
105
+ var eval_1 = require("./commands/eval");
106
+ Object.defineProperty(exports, "runEval", { enumerable: true, get: function () { return eval_1.runEval; } });
107
+ var fingerprint_1 = require("./config/fingerprint");
108
+ Object.defineProperty(exports, "configFingerprint", { enumerable: true, get: function () { return fingerprint_1.configFingerprint; } });
109
+ var loader_1 = require("./config/loader");
110
+ Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return loader_1.loadConfig; } });
111
+ Object.defineProperty(exports, "safegresConfigLoader", { enumerable: true, get: function () { return loader_1.safegresConfigLoader; } });
112
+ var presets_1 = require("./config/presets");
113
+ Object.defineProperty(exports, "constructive", { enumerable: true, get: function () { return presets_1.constructive; } });
114
+ Object.defineProperty(exports, "graphile", { enumerable: true, get: function () { return presets_1.graphile; } });
115
+ Object.defineProperty(exports, "hasura", { enumerable: true, get: function () { return presets_1.hasura; } });
116
+ Object.defineProperty(exports, "minimal", { enumerable: true, get: function () { return presets_1.minimal; } });
117
+ Object.defineProperty(exports, "multiTenant", { enumerable: true, get: function () { return presets_1.multiTenant; } });
118
+ Object.defineProperty(exports, "oltp", { enumerable: true, get: function () { return presets_1.oltp; } });
119
+ Object.defineProperty(exports, "postgrest", { enumerable: true, get: function () { return presets_1.postgrest; } });
120
+ Object.defineProperty(exports, "PRESETS", { enumerable: true, get: function () { return presets_1.PRESETS; } });
121
+ Object.defineProperty(exports, "recommended", { enumerable: true, get: function () { return presets_1.recommended; } });
122
+ Object.defineProperty(exports, "strict", { enumerable: true, get: function () { return presets_1.strict; } });
123
+ Object.defineProperty(exports, "supabase", { enumerable: true, get: function () { return presets_1.supabase; } });
124
+ var resolve_1 = require("./config/resolve");
125
+ Object.defineProperty(exports, "allAstRulesDisabled", { enumerable: true, get: function () { return resolve_1.allAstRulesDisabled; } });
126
+ Object.defineProperty(exports, "applyRulesToFindings", { enumerable: true, get: function () { return resolve_1.applyRulesToFindings; } });
127
+ Object.defineProperty(exports, "ConfigValidationError", { enumerable: true, get: function () { return resolve_1.ConfigValidationError; } });
128
+ Object.defineProperty(exports, "defaultRuleMap", { enumerable: true, get: function () { return resolve_1.defaultRuleMap; } });
129
+ Object.defineProperty(exports, "matchTablePattern", { enumerable: true, get: function () { return resolve_1.matchTablePattern; } });
130
+ Object.defineProperty(exports, "resolveRules", { enumerable: true, get: function () { return resolve_1.resolveRules; } });
131
+ Object.defineProperty(exports, "ruleCodesForDimension", { enumerable: true, get: function () { return resolve_1.ruleCodesForDimension; } });
132
+ Object.defineProperty(exports, "rulesForTable", { enumerable: true, get: function () { return resolve_1.rulesForTable; } });
133
+ var schema_1 = require("./config/schema");
134
+ Object.defineProperty(exports, "CONFIG_SHAPE", { enumerable: true, get: function () { return schema_1.CONFIG_SHAPE; } });
135
+ Object.defineProperty(exports, "SCHEMA_ID", { enumerable: true, get: function () { return schema_1.SCHEMA_ID; } });
136
+ Object.defineProperty(exports, "toJsonSchema", { enumerable: true, get: function () { return schema_1.toJsonSchema; } });
137
+ var validate_1 = require("./config/validate");
138
+ Object.defineProperty(exports, "validateConfigShape", { enumerable: true, get: function () { return validate_1.validateConfigShape; } });
139
+ var corpus_1 = require("./corpus");
140
+ Object.defineProperty(exports, "corpusBootstrap", { enumerable: true, get: function () { return corpus_1.corpusBootstrap; } });
141
+ Object.defineProperty(exports, "corpusDir", { enumerable: true, get: function () { return corpus_1.corpusDir; } });
142
+ Object.defineProperty(exports, "gradeCase", { enumerable: true, get: function () { return corpus_1.gradeCase; } });
143
+ Object.defineProperty(exports, "loadCase", { enumerable: true, get: function () { return corpus_1.loadCase; } });
144
+ Object.defineProperty(exports, "loadCorpus", { enumerable: true, get: function () { return corpus_1.loadCorpus; } });
145
+ var adapters_1 = require("./exposure/adapters");
146
+ Object.defineProperty(exports, "BUILTIN_ADAPTERS", { enumerable: true, get: function () { return adapters_1.BUILTIN_ADAPTERS; } });
147
+ Object.defineProperty(exports, "constructiveAdapter", { enumerable: true, get: function () { return adapters_1.constructiveAdapter; } });
148
+ Object.defineProperty(exports, "definePlanes", { enumerable: true, get: function () { return adapters_1.definePlanes; } });
149
+ Object.defineProperty(exports, "graphileAdapter", { enumerable: true, get: function () { return adapters_1.graphileAdapter; } });
150
+ Object.defineProperty(exports, "hasuraAdapter", { enumerable: true, get: function () { return adapters_1.hasuraAdapter; } });
151
+ Object.defineProperty(exports, "postgraphileAdapter", { enumerable: true, get: function () { return adapters_1.postgraphileAdapter; } });
152
+ Object.defineProperty(exports, "postgrestAdapter", { enumerable: true, get: function () { return adapters_1.postgrestAdapter; } });
153
+ Object.defineProperty(exports, "resolveAdapters", { enumerable: true, get: function () { return adapters_1.resolveAdapters; } });
154
+ Object.defineProperty(exports, "supabaseAdapter", { enumerable: true, get: function () { return adapters_1.supabaseAdapter; } });
155
+ var planes_1 = require("./exposure/planes");
156
+ Object.defineProperty(exports, "onPlane", { enumerable: true, get: function () { return planes_1.onPlane; } });
157
+ Object.defineProperty(exports, "relationKey", { enumerable: true, get: function () { return planes_1.relationKey; } });
158
+ Object.defineProperty(exports, "resolvePlaneReach", { enumerable: true, get: function () { return planes_1.resolvePlaneReach; } });
159
+ Object.defineProperty(exports, "scorePlane", { enumerable: true, get: function () { return planes_1.scorePlane; } });
160
+ Object.defineProperty(exports, "stampPlanes", { enumerable: true, get: function () { return planes_1.stampPlanes; } });
161
+ var reach_1 = require("./exposure/reach");
162
+ Object.defineProperty(exports, "BACKWARD_ABILITIES", { enumerable: true, get: function () { return reach_1.BACKWARD_ABILITIES; } });
163
+ Object.defineProperty(exports, "computeApiReach", { enumerable: true, get: function () { return reach_1.computeApiReach; } });
164
+ Object.defineProperty(exports, "FORWARD_ABILITIES", { enumerable: true, get: function () { return reach_1.FORWARD_ABILITIES; } });
165
+ Object.defineProperty(exports, "ROOT_ABILITIES", { enumerable: true, get: function () { return reach_1.ROOT_ABILITIES; } });
166
+ var baseline_3 = require("./perf/baseline");
167
+ Object.defineProperty(exports, "diffPerf", { enumerable: true, get: function () { return baseline_3.diffPerf; } });
168
+ Object.defineProperty(exports, "findingKey", { enumerable: true, get: function () { return baseline_3.findingKey; } });
169
+ Object.defineProperty(exports, "parsePerfBaseline", { enumerable: true, get: function () { return baseline_3.parsePerfBaseline; } });
170
+ Object.defineProperty(exports, "serializePerfBaseline", { enumerable: true, get: function () { return baseline_3.serializePerfBaseline; } });
171
+ Object.defineProperty(exports, "subjectOf", { enumerable: true, get: function () { return baseline_3.subjectOf; } });
172
+ Object.defineProperty(exports, "toBaselineFinding", { enumerable: true, get: function () { return baseline_3.toBaselineFinding; } });
173
+ Object.defineProperty(exports, "toPerfBaseline", { enumerable: true, get: function () { return baseline_3.toPerfBaseline; } });
174
+ var explain_1 = require("./perf/explain");
175
+ Object.defineProperty(exports, "proveFindings", { enumerable: true, get: function () { return explain_1.proveFindings; } });
176
+ var acl_1 = require("./pg/acl");
177
+ Object.defineProperty(exports, "introspectRoleGraph", { enumerable: true, get: function () { return acl_1.introspectRoleGraph; } });
178
+ Object.defineProperty(exports, "introspectSchemaAcls", { enumerable: true, get: function () { return acl_1.introspectSchemaAcls; } });
179
+ var exposure_1 = require("./pg/exposure");
180
+ Object.defineProperty(exports, "resolveConstructiveExposure", { enumerable: true, get: function () { return exposure_1.resolveConstructiveExposure; } });
181
+ Object.defineProperty(exports, "resolveExposure", { enumerable: true, get: function () { return exposure_1.resolveExposure; } });
182
+ Object.defineProperty(exports, "resolvePlanes", { enumerable: true, get: function () { return exposure_1.resolvePlanes; } });
183
+ Object.defineProperty(exports, "resolveReach", { enumerable: true, get: function () { return exposure_1.resolveReach; } });
184
+ Object.defineProperty(exports, "UNKNOWN_EXPOSURE", { enumerable: true, get: function () { return exposure_1.UNKNOWN_EXPOSURE; } });
185
+ var functions_1 = require("./pg/functions");
186
+ Object.defineProperty(exports, "introspectFunctions", { enumerable: true, get: function () { return functions_1.introspectFunctions; } });
187
+ var indexes_2 = require("./pg/indexes");
188
+ Object.defineProperty(exports, "introspectIndexes", { enumerable: true, get: function () { return indexes_2.introspectIndexes; } });
189
+ Object.defineProperty(exports, "introspectViews", { enumerable: true, get: function () { return indexes_2.introspectViews; } });
190
+ var introspect_1 = require("./pg/introspect");
191
+ Object.defineProperty(exports, "introspectTables", { enumerable: true, get: function () { return introspect_1.introspectTables; } });
192
+ var objects_1 = require("./pg/objects");
193
+ Object.defineProperty(exports, "introspectObjectAcls", { enumerable: true, get: function () { return objects_1.introspectObjectAcls; } });
194
+ var roles_1 = require("./pg/roles");
195
+ Object.defineProperty(exports, "listAuditableRoles", { enumerable: true, get: function () { return roles_1.listAuditableRoles; } });
196
+ Object.defineProperty(exports, "resolveRoles", { enumerable: true, get: function () { return roles_1.resolveRoles; } });
197
+ var stats_2 = require("./pg/stats");
198
+ Object.defineProperty(exports, "introspectStats", { enumerable: true, get: function () { return stats_2.introspectStats; } });
199
+ var callgraph_1 = require("./report/callgraph");
200
+ Object.defineProperty(exports, "renderCallGraph", { enumerable: true, get: function () { return callgraph_1.renderCallGraph; } });
201
+ Object.defineProperty(exports, "renderCallGraphDiff", { enumerable: true, get: function () { return callgraph_1.renderCallGraphDiff; } });
202
+ var compare_1 = require("./report/compare");
203
+ Object.defineProperty(exports, "baselineLabel", { enumerable: true, get: function () { return compare_1.baselineLabel; } });
204
+ Object.defineProperty(exports, "compareReports", { enumerable: true, get: function () { return compare_1.compareReports; } });
205
+ Object.defineProperty(exports, "describeBaseline", { enumerable: true, get: function () { return compare_1.describeBaseline; } });
206
+ Object.defineProperty(exports, "formatAge", { enumerable: true, get: function () { return compare_1.formatAge; } });
207
+ Object.defineProperty(exports, "formatDelta", { enumerable: true, get: function () { return compare_1.formatDelta; } });
208
+ Object.defineProperty(exports, "parseSnapshot", { enumerable: true, get: function () { return compare_1.parseSnapshot; } });
209
+ Object.defineProperty(exports, "serializeSnapshot", { enumerable: true, get: function () { return compare_1.serializeSnapshot; } });
210
+ Object.defineProperty(exports, "toSnapshot", { enumerable: true, get: function () { return compare_1.toSnapshot; } });
211
+ var github_2 = require("./report/github");
212
+ Object.defineProperty(exports, "COMMENT_MARKER", { enumerable: true, get: function () { return github_2.COMMENT_MARKER; } });
213
+ Object.defineProperty(exports, "emitGithub", { enumerable: true, get: function () { return github_2.emitGithub; } });
214
+ Object.defineProperty(exports, "gradeBadge", { enumerable: true, get: function () { return github_2.gradeBadge; } });
215
+ Object.defineProperty(exports, "postStickyComment", { enumerable: true, get: function () { return github_2.postStickyComment; } });
216
+ Object.defineProperty(exports, "renderAnnotations", { enumerable: true, get: function () { return github_2.renderAnnotations; } });
217
+ Object.defineProperty(exports, "renderGithubComment", { enumerable: true, get: function () { return github_2.renderGithubComment; } });
218
+ Object.defineProperty(exports, "renderGithubSummary", { enumerable: true, get: function () { return github_2.renderGithubSummary; } });
219
+ Object.defineProperty(exports, "scoreBadge", { enumerable: true, get: function () { return github_2.scoreBadge; } });
220
+ var json_1 = require("./report/json");
221
+ Object.defineProperty(exports, "renderJson", { enumerable: true, get: function () { return json_1.renderJson; } });
222
+ var markdown_1 = require("./report/markdown");
223
+ Object.defineProperty(exports, "renderMarkdown", { enumerable: true, get: function () { return markdown_1.renderMarkdown; } });
224
+ var pretty_1 = require("./report/pretty");
225
+ Object.defineProperty(exports, "renderPretty", { enumerable: true, get: function () { return pretty_1.renderPretty; } });
226
+ var sarif_1 = require("./report/sarif");
227
+ Object.defineProperty(exports, "buildSourceIndex", { enumerable: true, get: function () { return sarif_1.buildSourceIndex; } });
228
+ Object.defineProperty(exports, "renderSarif", { enumerable: true, get: function () { return sarif_1.renderSarif; } });
229
+ var view_1 = require("./report/view");
230
+ Object.defineProperty(exports, "ALL_SECTIONS", { enumerable: true, get: function () { return view_1.ALL_SECTIONS; } });
231
+ Object.defineProperty(exports, "matchPlane", { enumerable: true, get: function () { return view_1.matchPlane; } });
232
+ Object.defineProperty(exports, "selectView", { enumerable: true, get: function () { return view_1.selectView; } });
233
+ Object.defineProperty(exports, "viewConfigFromReportConfig", { enumerable: true, get: function () { return view_1.viewConfigFromReportConfig; } });
234
+ var registry_1 = require("./rules/registry");
235
+ Object.defineProperty(exports, "dimensionOf", { enumerable: true, get: function () { return registry_1.dimensionOf; } });
236
+ Object.defineProperty(exports, "expandRuleSelector", { enumerable: true, get: function () { return registry_1.expandRuleSelector; } });
237
+ Object.defineProperty(exports, "isKnownRule", { enumerable: true, get: function () { return registry_1.isKnownRule; } });
238
+ Object.defineProperty(exports, "RULES", { enumerable: true, get: function () { return registry_1.RULES; } });
239
+ Object.defineProperty(exports, "RULES_BY_CODE", { enumerable: true, get: function () { return registry_1.RULES_BY_CODE; } });
240
+ var score_1 = require("./score/score");
241
+ Object.defineProperty(exports, "computeScore", { enumerable: true, get: function () { return score_1.computeScore; } });
242
+ Object.defineProperty(exports, "DEFAULT_GRADE_BANDS", { enumerable: true, get: function () { return score_1.DEFAULT_GRADE_BANDS; } });
243
+ Object.defineProperty(exports, "DEFAULT_WEIGHTS", { enumerable: true, get: function () { return score_1.DEFAULT_WEIGHTS; } });
244
+ Object.defineProperty(exports, "meetsGrade", { enumerable: true, get: function () { return score_1.meetsGrade; } });
245
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Source-level SQL/PL/pgSQL convention linter.
3
+ *
4
+ * This module used to carry safegres's own copy of the linter. It now lives in
5
+ * the standalone `@pgsql/lint` package (source text in → findings out, no `pg`
6
+ * dependency); safegres consumes it as "the catalog adapter", feeding it the
7
+ * `pg_get_functiondef` text it already reads. This file is a thin re-export so
8
+ * the rest of safegres keeps importing from `../lint` unchanged.
9
+ */
10
+ export type { DynamicSqlSite, LintOptions, LintProblem, LintResult, LintRule, LintRuleMeta, LintUnit, SqlFragment, SuppressedProblem, SuppressionScope } from '@pgsql/lint';
11
+ export { LINT_RULES, LINT_RULES_BY_CODE, LINT_RULES_BY_ID, lintDefinition, parseUnit, Suppressions } from '@pgsql/lint';
package/lint/index.js ADDED
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ /**
3
+ * Source-level SQL/PL/pgSQL convention linter.
4
+ *
5
+ * This module used to carry safegres's own copy of the linter. It now lives in
6
+ * the standalone `@pgsql/lint` package (source text in → findings out, no `pg`
7
+ * dependency); safegres consumes it as "the catalog adapter", feeding it the
8
+ * `pg_get_functiondef` text it already reads. This file is a thin re-export so
9
+ * the rest of safegres keeps importing from `../lint` unchanged.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Suppressions = exports.parseUnit = exports.lintDefinition = exports.LINT_RULES_BY_ID = exports.LINT_RULES_BY_CODE = exports.LINT_RULES = void 0;
13
+ var lint_1 = require("@pgsql/lint");
14
+ Object.defineProperty(exports, "LINT_RULES", { enumerable: true, get: function () { return lint_1.LINT_RULES; } });
15
+ Object.defineProperty(exports, "LINT_RULES_BY_CODE", { enumerable: true, get: function () { return lint_1.LINT_RULES_BY_CODE; } });
16
+ Object.defineProperty(exports, "LINT_RULES_BY_ID", { enumerable: true, get: function () { return lint_1.LINT_RULES_BY_ID; } });
17
+ Object.defineProperty(exports, "lintDefinition", { enumerable: true, get: function () { return lint_1.lintDefinition; } });
18
+ Object.defineProperty(exports, "parseUnit", { enumerable: true, get: function () { return lint_1.parseUnit; } });
19
+ Object.defineProperty(exports, "Suppressions", { enumerable: true, get: function () { return lint_1.Suppressions; } });
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@safegres/test",
3
- "version": "0.0.2",
4
- "author": "Dan Lynch <pyramation@gmail.com>",
5
- "description": "safegres offers isolated, role-aware, and rollback-friendly PostgreSQL environments for integration tests — giving developers realistic test coverage without external state pollution",
3
+ "version": "1.30.7",
4
+ "author": "Constructive <developers@constructive.io>",
5
+ "description": "Postgres security and performance auditor: RLS, grants and effective-access analysis plus index and policy-cost checks, scored on two independent axes. One connection, no framework.",
6
6
  "main": "index.js",
7
7
  "module": "esm/index.js",
8
8
  "types": "index.d.ts",
9
- "homepage": "https://github.com/launchql/launchql",
9
+ "homepage": "https://github.com/constructive-io/constructive",
10
10
  "license": "MIT",
11
11
  "publishConfig": {
12
12
  "access": "public",
@@ -14,59 +14,65 @@
14
14
  },
15
15
  "repository": {
16
16
  "type": "git",
17
- "url": "https://github.com/launchql/launchql"
17
+ "url": "https://github.com/constructive-io/constructive"
18
18
  },
19
19
  "bugs": {
20
- "url": "https://github.com/launchql/launchql/issues"
20
+ "url": "https://github.com/constructive-io/constructive/issues"
21
+ },
22
+ "bin": {
23
+ "safegres": "cli.js"
21
24
  },
22
25
  "keywords": [
23
26
  "postgres",
24
27
  "postgresql",
25
- "testing",
26
- "integration-tests",
27
- "database-testing",
28
- "pg",
28
+ "database",
29
+ "security",
30
+ "performance",
29
31
  "rls",
30
- "role-based-access",
31
- "test-database",
32
- "test-runner",
33
- "jest",
34
- "mocha",
35
- "sqitch",
36
- "launchql",
37
- "graphile",
38
- "typeorm",
39
- "knex",
40
- "seed",
41
- "fixtures",
42
- "transactions",
43
- "rollback",
44
- "node-postgres",
45
- "pg-pool",
46
- "pg-client"
32
+ "row-level-security",
33
+ "audit",
34
+ "auditor",
35
+ "linter",
36
+ "static-analysis",
37
+ "index",
38
+ "indexing",
39
+ "query-performance",
40
+ "explain",
41
+ "grants",
42
+ "policy",
43
+ "sarif",
44
+ "ci",
45
+ "devsecops",
46
+ "dba",
47
+ "safegres"
47
48
  ],
48
- "scripts": {
49
- "copy": "copyfiles -f ../../LICENSE README.md package.json dist",
50
- "clean": "rimraf dist/**",
51
- "prepare": "npm run build",
52
- "build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy",
53
- "build:dev": "npm run clean; tsc --declarationMap; tsc -p tsconfig.esm.json; npm run copy",
54
- "lint": "eslint . --fix",
55
- "test": "jest",
56
- "test:watch": "jest --watch"
49
+ "dependencies": {
50
+ "@inquirerer/utils": "^3.3.13",
51
+ "@pgpmjs/logger": "^2.27.0",
52
+ "@pgsql/lint": "^18.3.5",
53
+ "@pgsql/traverse": "^18.8.3",
54
+ "@pgsql/types": "^18.0.0",
55
+ "confstash": "^0.1.2",
56
+ "inquirerer": "^4.9.4",
57
+ "libpg-query": "^18.2.0",
58
+ "pg": "^8.21.0",
59
+ "pg-env": "^1.33.0",
60
+ "pgsql-deparser": "^18.4.3",
61
+ "pgsql-parser": "^18.3.3",
62
+ "yanse": "^0.2.2"
57
63
  },
58
- "devDependencies": {
59
- "@types/pg": "^8.15.2",
60
- "@types/pg-copy-streams": "^1.2.5"
64
+ "peerDependencies": {
65
+ "pgsql-test": "*"
61
66
  },
62
- "dependencies": {
63
- "@launchql/core": "^2.11.1",
64
- "@launchql/env": "^2.4.1",
65
- "@launchql/server-utils": "^2.4.1",
66
- "@launchql/types": "^2.6.0",
67
- "pg": "^8.16.0",
68
- "pg-cache": "^1.3.1",
69
- "pg-copy-streams": "^6.0.6",
70
- "pg-env": "^1.1.0"
67
+ "peerDependenciesMeta": {
68
+ "pgsql-test": {
69
+ "optional": true
70
+ }
71
+ },
72
+ "devDependencies": {
73
+ "@types/node": "^22.0.0",
74
+ "@types/pg": "^8.20.4",
75
+ "makage": "^0.8.0",
76
+ "pgsql-test": "^5.20.6"
71
77
  }
72
78
  }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Perf baseline: a committed snapshot of accepted performance debt.
3
+ *
4
+ * The point is the ratchet. A large schema will not reach a clean perf report
5
+ * in one pass, but it can refuse to get worse: commit the current findings,
6
+ * then fail CI only on findings that are *not* in the baseline.
7
+ *
8
+ * Only the identity of a finding is stored — code, relation, policy, and the
9
+ * one context field that distinguishes findings of the same code on the same
10
+ * relation. Messages, severities and hints may be reworded between safegres
11
+ * versions without invalidating a committed baseline.
12
+ */
13
+ import type { Finding } from '../types';
14
+ export interface PerfBaseline {
15
+ version: 1;
16
+ findings: BaselineFinding[];
17
+ }
18
+ export interface BaselineFinding {
19
+ code: string;
20
+ schema?: string;
21
+ table?: string;
22
+ policy?: string;
23
+ /** The rule-specific subject: constraint, index, column, expression, or function. */
24
+ subject?: string;
25
+ }
26
+ export interface PerfDiff {
27
+ /** Findings present now but absent from the baseline — new debt. */
28
+ added: Finding[];
29
+ /** Baseline entries no longer produced — fixed, or the relation is gone. */
30
+ removed: BaselineFinding[];
31
+ /** Findings that matched the baseline — accepted debt, still reported. */
32
+ accepted: Finding[];
33
+ }
34
+ export declare function subjectOf(finding: Finding): string | undefined;
35
+ export declare function findingKey(entry: BaselineFinding): string;
36
+ export declare function toBaselineFinding(finding: Finding): BaselineFinding;
37
+ export declare function toPerfBaseline(findings: Finding[]): PerfBaseline;
38
+ export declare function diffPerf(findings: Finding[], baseline: PerfBaseline): PerfDiff;
39
+ export declare function parsePerfBaseline(raw: string): PerfBaseline;
40
+ export declare function serializePerfBaseline(baseline: PerfBaseline): string;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ /**
3
+ * Perf baseline: a committed snapshot of accepted performance debt.
4
+ *
5
+ * The point is the ratchet. A large schema will not reach a clean perf report
6
+ * in one pass, but it can refuse to get worse: commit the current findings,
7
+ * then fail CI only on findings that are *not* in the baseline.
8
+ *
9
+ * Only the identity of a finding is stored — code, relation, policy, and the
10
+ * one context field that distinguishes findings of the same code on the same
11
+ * relation. Messages, severities and hints may be reworded between safegres
12
+ * versions without invalidating a committed baseline.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.subjectOf = subjectOf;
16
+ exports.findingKey = findingKey;
17
+ exports.toBaselineFinding = toBaselineFinding;
18
+ exports.toPerfBaseline = toPerfBaseline;
19
+ exports.diffPerf = diffPerf;
20
+ exports.parsePerfBaseline = parsePerfBaseline;
21
+ exports.serializePerfBaseline = serializePerfBaseline;
22
+ /**
23
+ * Context keys that identify *which* object a finding is about, in priority
24
+ * order (X3 carries both `expression` and `column`; the expression is the
25
+ * narrower identity). Rules that can only fire once per relation — X6 — set
26
+ * none of these and are keyed by code + relation alone.
27
+ */
28
+ const SUBJECT_KEYS = ['constraint', 'index', 'expression', 'column', 'function'];
29
+ function subjectOf(finding) {
30
+ const context = finding.context;
31
+ if (!context)
32
+ return undefined;
33
+ for (const key of SUBJECT_KEYS) {
34
+ const value = context[key];
35
+ if (typeof value === 'string' && value.length > 0)
36
+ return value;
37
+ }
38
+ return undefined;
39
+ }
40
+ function findingKey(entry) {
41
+ return [entry.code, entry.schema ?? '', entry.table ?? '', entry.policy ?? '', entry.subject ?? ''].join('|');
42
+ }
43
+ function toBaselineFinding(finding) {
44
+ const subject = subjectOf(finding);
45
+ return {
46
+ code: finding.code,
47
+ ...(finding.schema ? { schema: finding.schema } : {}),
48
+ ...(finding.table ? { table: finding.table } : {}),
49
+ ...(finding.policy ? { policy: finding.policy } : {}),
50
+ ...(subject ? { subject } : {})
51
+ };
52
+ }
53
+ function toPerfBaseline(findings) {
54
+ const seen = new Set();
55
+ const out = [];
56
+ for (const finding of findings) {
57
+ const entry = toBaselineFinding(finding);
58
+ const key = findingKey(entry);
59
+ if (seen.has(key))
60
+ continue;
61
+ seen.add(key);
62
+ out.push(entry);
63
+ }
64
+ out.sort((a, b) => findingKey(a).localeCompare(findingKey(b)));
65
+ return { version: 1, findings: out };
66
+ }
67
+ function diffPerf(findings, baseline) {
68
+ const baseKeys = new Set(baseline.findings.map(findingKey));
69
+ const currentKeys = new Set();
70
+ const added = [];
71
+ const accepted = [];
72
+ for (const finding of findings) {
73
+ const key = findingKey(toBaselineFinding(finding));
74
+ currentKeys.add(key);
75
+ if (baseKeys.has(key))
76
+ accepted.push(finding);
77
+ else
78
+ added.push(finding);
79
+ }
80
+ const removed = baseline.findings.filter((entry) => !currentKeys.has(findingKey(entry)));
81
+ return { added, removed, accepted };
82
+ }
83
+ function parsePerfBaseline(raw) {
84
+ const data = JSON.parse(raw);
85
+ if (data.version !== 1 || !Array.isArray(data.findings)) {
86
+ throw new Error('invalid perf baseline: expected { version: 1, findings: [...] }');
87
+ }
88
+ return { version: 1, findings: data.findings };
89
+ }
90
+ function serializePerfBaseline(baseline) {
91
+ return JSON.stringify(baseline, null, 2) + '\n';
92
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Proof by EXPLAIN (`--explain`).
3
+ *
4
+ * The `X*` rules infer from the catalog that a query *shape* has no index to
5
+ * serve it. This turns the inference into evidence: for each finding that has
6
+ * a probe shape, plan the query the finding is about and read the plan back.
7
+ *
8
+ * The planner is the authority, so the interesting outcome is disagreement —
9
+ * a finding whose probe plans as an index scan is **refuted** (some index the
10
+ * catalog rules didn't credit does serve it) and stops counting against the
11
+ * score. The reverse is not symmetrical: an empty or unanalyzed table always
12
+ * seq-scans, so a seq scan only *confirms* a finding above the row floor;
13
+ * below it the probe is inconclusive and the finding is left exactly as it
14
+ * was.
15
+ *
16
+ * Probes use `EXPLAIN (GENERIC_PLAN)` — parameters stay parameters, nothing
17
+ * is executed, and no value has to be invented for a column whose domain we
18
+ * know nothing about. That requires PostgreSQL 16+.
19
+ */
20
+ import type { TableIndexSnapshot } from '../pg/indexes';
21
+ import type { QueryExecutor } from '../pg/introspect';
22
+ import type { Finding } from '../types';
23
+ export interface ExplainOptions {
24
+ /**
25
+ * Below this planner row estimate a sequential scan is the correct plan, so
26
+ * a seq-scan result proves nothing. Default 1000.
27
+ */
28
+ minRows?: number;
29
+ }
30
+ export interface ExplainReport {
31
+ /** Findings that were probed. */
32
+ probed: number;
33
+ /** Probes whose plan showed the scan the finding predicted. */
34
+ confirmed: number;
35
+ /** Probes the planner served with an index — the finding was wrong. */
36
+ refuted: number;
37
+ /** Probes on tables too small for the plan to mean anything. */
38
+ inconclusive: number;
39
+ /** Why probing was skipped entirely, when it was. */
40
+ unavailable?: string;
41
+ }
42
+ /**
43
+ * Plan a probe for every probeable perf finding and annotate it in place.
44
+ * Findings the planner refutes are acknowledged (reported, unscored).
45
+ */
46
+ export declare function proveFindings(exec: QueryExecutor, findings: Finding[], tables: Map<string, TableIndexSnapshot>, options?: ExplainOptions): Promise<ExplainReport>;