@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,74 @@
1
+ /**
2
+ * GitHub Actions output: job summary, workflow annotations, and a sticky PR
3
+ * comment.
4
+ *
5
+ * This is a *renderer*, not a second audit — everything here reads the same
6
+ * `ReportView` the terminal renderer reads, so what CI says and what a
7
+ * developer sees locally cannot disagree.
8
+ *
9
+ * On color: GitHub Markdown has none. The only way to get a real green/red
10
+ * score is an image, so scores render as shields.io badges by default, with
11
+ * 🟢/🟡/🔴 as the offline fallback (`report.github.badges: false`).
12
+ */
13
+ import type { GithubReportConfig } from '../config/types';
14
+ import type { Grade } from '../config/types';
15
+ import type { Score } from '../score/score';
16
+ import type { Finding, Report } from '../types';
17
+ import { type ViewConfig } from './view';
18
+ /** Marker that makes the PR comment sticky: one comment, edited in place. */
19
+ export declare const COMMENT_MARKER = "<!-- safegres-report -->";
20
+ export interface GithubRenderOptions {
21
+ config?: GithubReportConfig;
22
+ /** Findings that tripped a gate, for `annotations: 'gate-failures'`. */
23
+ gateFailures?: Finding[];
24
+ /** Extra view selection (planes, dimensions) from `report` config. */
25
+ view?: ViewConfig;
26
+ }
27
+ /** A score as a shields.io badge, or as a colored dot when badges are off. */
28
+ export declare function scoreBadge(label: string, score: Score, badges: boolean): string;
29
+ export declare function gradeBadge(label: string, grade: Grade, badges: boolean): string;
30
+ /**
31
+ * The job summary: the badges a reviewer reads first, then the full markdown
32
+ * report. `summary` picks which scores get a badge — `security`, `perf`, and
33
+ * `planes:<glob>` for the secondary planes a team cares about.
34
+ */
35
+ export declare function renderGithubSummary(report: Report, options?: GithubRenderOptions): string;
36
+ /**
37
+ * GitHub rejects an issue comment body over 65536 characters, and a comment
38
+ * that fails to post is worse than a short one — so a comment carrying the
39
+ * report degrades (verbose → normal → summary → a pointer at the job summary)
40
+ * rather than being truncated at a byte boundary by the API.
41
+ */
42
+ export declare const COMMENT_MAX_CHARS = 65536;
43
+ /**
44
+ * The sticky PR comment: shorter than the summary by default. A comment is read
45
+ * on the way past, so out of the box it carries the scores, the movement, and
46
+ * what is new, with the full finding tables in the job summary and the SARIF
47
+ * alerts.
48
+ *
49
+ * `comment.sections` chooses what it says. `report` puts the whole markdown
50
+ * report in the comment at `comment.detail` (default `summary`: scores,
51
+ * exposure, counts, the delta and the ratchet verdict — no per-finding tables),
52
+ * which is the same render the job summary uses, so the two cannot disagree.
53
+ */
54
+ export declare function renderGithubComment(report: Report, options?: GithubRenderOptions): string;
55
+ /**
56
+ * Workflow annotations. Default `gate-failures`: annotating every advisory on
57
+ * a large schema buries the one finding that actually blocked the merge.
58
+ */
59
+ export declare function renderAnnotations(report: Report, options?: GithubRenderOptions): string[];
60
+ /**
61
+ * Write the summary to `$GITHUB_STEP_SUMMARY` and print the annotations.
62
+ * Returns false when not running under GitHub Actions, so a caller can fall
63
+ * back to stdout rather than silently producing nothing.
64
+ */
65
+ export declare function emitGithub(report: Report, options?: GithubRenderOptions): boolean;
66
+ /**
67
+ * Upsert the sticky comment on the current pull request. No-op (returning a
68
+ * reason) when the environment has no PR or no token: a report is not worth
69
+ * failing a build over, but silence about *why* is how integrations rot.
70
+ */
71
+ export declare function postStickyComment(body: string, env?: NodeJS.ProcessEnv): Promise<{
72
+ posted: boolean;
73
+ reason?: string;
74
+ }>;
@@ -0,0 +1,333 @@
1
+ "use strict";
2
+ /**
3
+ * GitHub Actions output: job summary, workflow annotations, and a sticky PR
4
+ * comment.
5
+ *
6
+ * This is a *renderer*, not a second audit — everything here reads the same
7
+ * `ReportView` the terminal renderer reads, so what CI says and what a
8
+ * developer sees locally cannot disagree.
9
+ *
10
+ * On color: GitHub Markdown has none. The only way to get a real green/red
11
+ * score is an image, so scores render as shields.io badges by default, with
12
+ * 🟢/🟡/🔴 as the offline fallback (`report.github.badges: false`).
13
+ */
14
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ var desc = Object.getOwnPropertyDescriptor(m, k);
17
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
+ desc = { enumerable: true, get: function() { return m[k]; } };
19
+ }
20
+ Object.defineProperty(o, k2, desc);
21
+ }) : (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ o[k2] = m[k];
24
+ }));
25
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
26
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
27
+ }) : function(o, v) {
28
+ o["default"] = v;
29
+ });
30
+ var __importStar = (this && this.__importStar) || (function () {
31
+ var ownKeys = function(o) {
32
+ ownKeys = Object.getOwnPropertyNames || function (o) {
33
+ var ar = [];
34
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
35
+ return ar;
36
+ };
37
+ return ownKeys(o);
38
+ };
39
+ return function (mod) {
40
+ if (mod && mod.__esModule) return mod;
41
+ var result = {};
42
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
43
+ __setModuleDefault(result, mod);
44
+ return result;
45
+ };
46
+ })();
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.COMMENT_MAX_CHARS = exports.COMMENT_MARKER = void 0;
49
+ exports.scoreBadge = scoreBadge;
50
+ exports.gradeBadge = gradeBadge;
51
+ exports.renderGithubSummary = renderGithubSummary;
52
+ exports.renderGithubComment = renderGithubComment;
53
+ exports.renderAnnotations = renderAnnotations;
54
+ exports.emitGithub = emitGithub;
55
+ exports.postStickyComment = postStickyComment;
56
+ const fs = __importStar(require("fs"));
57
+ const compare_1 = require("./compare");
58
+ const markdown_1 = require("./markdown");
59
+ const view_1 = require("./view");
60
+ /** Marker that makes the PR comment sticky: one comment, edited in place. */
61
+ exports.COMMENT_MARKER = '<!-- safegres-report -->';
62
+ const GRADE_COLOR = {
63
+ 'A+': 'brightgreen',
64
+ A: 'brightgreen',
65
+ B: 'green',
66
+ C: 'yellow',
67
+ D: 'orange',
68
+ F: 'red'
69
+ };
70
+ const GRADE_DOT = {
71
+ 'A+': '🟢',
72
+ A: '🟢',
73
+ B: '🟢',
74
+ C: '🟡',
75
+ D: '🟠',
76
+ F: '🔴'
77
+ };
78
+ /** A score as a shields.io badge, or as a colored dot when badges are off. */
79
+ function scoreBadge(label, score, badges) {
80
+ const color = GRADE_COLOR[score.grade] ?? 'lightgrey';
81
+ if (!badges)
82
+ return `${GRADE_DOT[score.grade] ?? '⚪'} **${label} ${score.value} (${score.grade})**`;
83
+ const text = encodeURIComponent(`${score.value} (${score.grade})`);
84
+ const name = encodeURIComponent(label);
85
+ return `![${label} ${score.value} ${score.grade}](https://img.shields.io/badge/${name}-${text}-${color})`;
86
+ }
87
+ function gradeBadge(label, grade, badges) {
88
+ const color = GRADE_COLOR[grade] ?? 'lightgrey';
89
+ if (!badges)
90
+ return `${GRADE_DOT[grade] ?? '⚪'} **${label} ${grade}**`;
91
+ return `![${label} ${grade}](https://img.shields.io/badge/${encodeURIComponent(label)}-${grade}-${color})`;
92
+ }
93
+ /**
94
+ * The job summary: the badges a reviewer reads first, then the full markdown
95
+ * report. `summary` picks which scores get a badge — `security`, `perf`, and
96
+ * `planes:<glob>` for the secondary planes a team cares about.
97
+ */
98
+ function renderGithubSummary(report, options = {}) {
99
+ const config = options.config ?? {};
100
+ const badges = config.badges !== false;
101
+ const selectors = config.summary ?? ['security', 'perf'];
102
+ const viewConfig = {
103
+ planes: planePatterns(selectors),
104
+ ...(config.detail ? { detail: config.detail } : {}),
105
+ ...options.view
106
+ };
107
+ const view = (0, view_1.selectView)(report, viewConfig);
108
+ const out = [];
109
+ const line = selectedScores(view.scores, selectors)
110
+ .map((s) => scoreBadge(s.label, s.score, badges))
111
+ .join(' ');
112
+ if (line)
113
+ out.push(line, '');
114
+ out.push((0, markdown_1.renderMarkdown)(report, { view: viewConfig }));
115
+ return out.join('\n');
116
+ }
117
+ /**
118
+ * GitHub rejects an issue comment body over 65536 characters, and a comment
119
+ * that fails to post is worse than a short one — so a comment carrying the
120
+ * report degrades (verbose → normal → summary → a pointer at the job summary)
121
+ * rather than being truncated at a byte boundary by the API.
122
+ */
123
+ exports.COMMENT_MAX_CHARS = 65536;
124
+ /**
125
+ * The sticky PR comment: shorter than the summary by default. A comment is read
126
+ * on the way past, so out of the box it carries the scores, the movement, and
127
+ * what is new, with the full finding tables in the job summary and the SARIF
128
+ * alerts.
129
+ *
130
+ * `comment.sections` chooses what it says. `report` puts the whole markdown
131
+ * report in the comment at `comment.detail` (default `summary`: scores,
132
+ * exposure, counts, the delta and the ratchet verdict — no per-finding tables),
133
+ * which is the same render the job summary uses, so the two cannot disagree.
134
+ */
135
+ function renderGithubComment(report, options = {}) {
136
+ const wanted = options.config?.comment?.detail ?? 'summary';
137
+ const chain = wanted === 'verbose' ? ['verbose', 'normal', 'summary'] : wanted === 'normal' ? ['normal', 'summary'] : ['summary'];
138
+ for (const detail of chain) {
139
+ const body = commentBody(report, options, detail);
140
+ if (body.length <= exports.COMMENT_MAX_CHARS)
141
+ return body;
142
+ }
143
+ return commentBody(report, options, null);
144
+ }
145
+ /**
146
+ * One comment body. `detail` is the report section's detail, or null to drop
147
+ * the report and say where it went — which is how the size cap is honored.
148
+ */
149
+ function commentBody(report, options, detail) {
150
+ const config = options.config ?? {};
151
+ const badges = config.badges !== false;
152
+ const sections = new Set(config.comment?.sections ?? ['scores', 'delta', 'new-findings']);
153
+ const selectors = config.summary ?? ['security', 'perf'];
154
+ const view = (0, view_1.selectView)(report, { planes: planePatterns(selectors), ...options.view });
155
+ // `findings` is the old name for `report`; both mean "the markdown report".
156
+ const wantsReport = sections.has('report') || sections.has('findings');
157
+ const withReport = wantsReport && detail != null;
158
+ const out = [exports.COMMENT_MARKER, '## safegres', ''];
159
+ if (sections.has('scores')) {
160
+ out.push(selectedScores(view.scores, selectors)
161
+ .map((s) => scoreBadge(s.label, s.score, badges))
162
+ .join(' '), '');
163
+ // Everything below is in the report too, so it is said once.
164
+ if (report.exposure && !withReport) {
165
+ out.push(report.exposure.known
166
+ ? `Exposure (${report.exposure.source}): **${report.exposure.exposedTables}/`
167
+ + `${report.exposure.totalTables}** tables reachable.`
168
+ : '> [!WARNING]\n> Exposure unknown — the whole database is assumed reachable, '
169
+ + 'and the score is capped.', '');
170
+ }
171
+ }
172
+ if (sections.has('planes') && view.planes.length > 0) {
173
+ out.push('| Plane | Kind | Relations | Grade |', '| --- | --- | ---: | --- |', ...view.planes.map((p) => p.skipped
174
+ ? `| \`${p.name}\` | ${p.kind} | — | not graded |`
175
+ : `| \`${p.name}\` | ${p.kind} | ${p.exposedTables} | **${p.score.grade}** (${p.score.value}) |`), '');
176
+ }
177
+ // The report renders the comparison (or the reason there is none) itself.
178
+ const wantsDelta = sections.has('delta') && !withReport;
179
+ if (wantsDelta && report.comparison) {
180
+ const cmp = report.comparison;
181
+ const since = (0, compare_1.describeBaseline)(cmp.previous);
182
+ if (cmp.unchanged) {
183
+ out.push(`_No change since ${since}._`, '');
184
+ }
185
+ else {
186
+ out.push(`**Changes since ${since}**`, '');
187
+ for (const [dimension, d] of [
188
+ ['security', cmp.security],
189
+ ['performance', cmp.perf]
190
+ ]) {
191
+ if (!d)
192
+ continue;
193
+ const arrow = d.delta > 0 ? '🟢 ▲' : d.delta < 0 ? '🔴 ▼' : '⚪';
194
+ out.push(`- ${dimension}: ${arrow} ${d.delta > 0 ? '+' : ''}${d.delta.toFixed(1)} `
195
+ + `(${d.before} → ${d.after}${d.gradeBefore === d.gradeAfter ? '' : `, ${d.gradeBefore} → ${d.gradeAfter}`})`);
196
+ }
197
+ out.push('');
198
+ }
199
+ }
200
+ else if (wantsDelta && report.comparisonSkipped) {
201
+ out.push(`_No delta baseline: ${report.comparisonSkipped}. `
202
+ + 'The absolute score and the perf baseline still gate this run._', '');
203
+ }
204
+ if (sections.has('new-findings')) {
205
+ const diff = report.perf?.diff;
206
+ // The ratchet's verdict, even when it is "nothing new": a comment that only
207
+ // speaks up on new debt cannot be distinguished from one that never ran.
208
+ // The report carries this line itself, so it is not repeated under it.
209
+ if (diff && !withReport) {
210
+ out.push(`Perf baseline: **${diff.added.length} new**, ${diff.accepted.length} accepted, `
211
+ + `${diff.removed.length} resolved.`, '');
212
+ }
213
+ const added = diff?.added ?? [];
214
+ if (added.length > 0) {
215
+ out.push(`**${added.length} new performance finding${added.length === 1 ? '' : 's'} since the baseline**`, '', ...added.slice(0, 10).map((f) => `- \`${f.code}\` ${location(f)} — ${f.message}`), '');
216
+ }
217
+ }
218
+ if (withReport) {
219
+ out.push((0, markdown_1.renderMarkdown)(report, { title: 'Report', view: { detail, ...options.view } }), '');
220
+ }
221
+ else if (wantsReport) {
222
+ out.push('_The report is too large for a PR comment — it is in the job summary and the '
223
+ + 'reports artifact._', '');
224
+ }
225
+ return out.join('\n');
226
+ }
227
+ /**
228
+ * Workflow annotations. Default `gate-failures`: annotating every advisory on
229
+ * a large schema buries the one finding that actually blocked the merge.
230
+ */
231
+ function renderAnnotations(report, options = {}) {
232
+ const mode = options.config?.annotations ?? 'gate-failures';
233
+ if (mode === 'none')
234
+ return [];
235
+ const findings = mode === 'all'
236
+ ? report.findings.filter((f) => f.exposed !== false && !f.acknowledged)
237
+ : (options.gateFailures ?? []);
238
+ return findings.map((f) => {
239
+ const level = f.severity === 'critical' || f.severity === 'high' ? 'error' : 'warning';
240
+ const title = `${f.code} ${location(f)}`.trim();
241
+ return `::${level} title=${escapeProperty(title)}::${escapeData(f.message)}`;
242
+ });
243
+ }
244
+ /**
245
+ * Write the summary to `$GITHUB_STEP_SUMMARY` and print the annotations.
246
+ * Returns false when not running under GitHub Actions, so a caller can fall
247
+ * back to stdout rather than silently producing nothing.
248
+ */
249
+ function emitGithub(report, options = {}) {
250
+ const summaryPath = process.env.GITHUB_STEP_SUMMARY;
251
+ for (const annotation of renderAnnotations(report, options)) {
252
+ process.stdout.write(`${annotation}\n`);
253
+ }
254
+ if (!summaryPath)
255
+ return false;
256
+ fs.appendFileSync(summaryPath, `${renderGithubSummary(report, options)}\n`);
257
+ return true;
258
+ }
259
+ /**
260
+ * Upsert the sticky comment on the current pull request. No-op (returning a
261
+ * reason) when the environment has no PR or no token: a report is not worth
262
+ * failing a build over, but silence about *why* is how integrations rot.
263
+ */
264
+ async function postStickyComment(body, env = process.env) {
265
+ const token = env.GITHUB_TOKEN ?? env.INPUT_GITHUB_TOKEN;
266
+ const repo = env.GITHUB_REPOSITORY;
267
+ if (!token)
268
+ return { posted: false, reason: 'no GITHUB_TOKEN in the environment' };
269
+ if (!repo)
270
+ return { posted: false, reason: 'no GITHUB_REPOSITORY in the environment' };
271
+ const pr = pullRequestNumber(env);
272
+ if (pr == null)
273
+ return { posted: false, reason: 'not running on a pull_request event' };
274
+ const api = env.GITHUB_API_URL ?? 'https://api.github.com';
275
+ const headers = {
276
+ accept: 'application/vnd.github+json',
277
+ authorization: `Bearer ${token}`,
278
+ 'content-type': 'application/json'
279
+ };
280
+ const listed = await fetch(`${api}/repos/${repo}/issues/${pr}/comments?per_page=100`, { headers });
281
+ if (!listed.ok) {
282
+ return { posted: false, reason: `GitHub API ${listed.status} listing comments` };
283
+ }
284
+ const comments = (await listed.json());
285
+ const existing = comments.find((c) => c.body?.includes(exports.COMMENT_MARKER));
286
+ const target = existing
287
+ ? `${api}/repos/${repo}/issues/comments/${existing.id}`
288
+ : `${api}/repos/${repo}/issues/${pr}/comments`;
289
+ const written = await fetch(target, {
290
+ method: existing ? 'PATCH' : 'POST',
291
+ headers,
292
+ body: JSON.stringify({ body })
293
+ });
294
+ if (!written.ok)
295
+ return { posted: false, reason: `GitHub API ${written.status} writing comment` };
296
+ return { posted: true };
297
+ }
298
+ function pullRequestNumber(env) {
299
+ const eventPath = env.GITHUB_EVENT_PATH;
300
+ if (!eventPath || !fs.existsSync(eventPath))
301
+ return null;
302
+ try {
303
+ const event = JSON.parse(fs.readFileSync(eventPath, 'utf8'));
304
+ return event.pull_request?.number ?? event.issue?.number ?? null;
305
+ }
306
+ catch {
307
+ return null;
308
+ }
309
+ }
310
+ /** `planes:direct:*` in a summary selector is a plane glob for the view. */
311
+ function planePatterns(selectors) {
312
+ return selectors
313
+ .filter((s) => s.startsWith('planes:'))
314
+ .map((s) => s.slice('planes:'.length));
315
+ }
316
+ function selectedScores(scores, selectors) {
317
+ const planes = planePatterns(selectors);
318
+ return scores.filter((s) => {
319
+ if (s.plane)
320
+ return planes.some((p) => (0, view_1.matchPlane)(p, s.plane.name));
321
+ return selectors.includes(s.id);
322
+ });
323
+ }
324
+ function location(f) {
325
+ return [f.schema, f.table].filter(Boolean).join('.') + (f.policy ? ` (${f.policy})` : '');
326
+ }
327
+ // https://github.com/actions/toolkit/blob/main/packages/core/src/command.ts
328
+ function escapeData(value) {
329
+ return value.replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A');
330
+ }
331
+ function escapeProperty(value) {
332
+ return escapeData(value).replace(/:/g, '%3A').replace(/,/g, '%2C');
333
+ }
@@ -0,0 +1,4 @@
1
+ import type { Report } from '../types';
2
+ export declare function renderJson(report: Report, options?: {
3
+ pretty?: boolean;
4
+ }): string;
package/report/json.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderJson = renderJson;
4
+ function renderJson(report, options = {}) {
5
+ return options.pretty ? JSON.stringify(report, null, 2) : JSON.stringify(report);
6
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Markdown rendering (`--format markdown`), for the places CI reads a report:
3
+ * a GitHub job summary (`$GITHUB_STEP_SUMMARY`) or a PR comment.
4
+ *
5
+ * The pretty renderer is a terminal artifact — ANSI colors, fixed-width
6
+ * severity labels, a long scrollable list. A PR comment is read once, by
7
+ * someone deciding whether to look further, so this renders the same report
8
+ * as tables: scores first, then findings grouped by rule, with the noisy
9
+ * parts (internal advisories, accepted debt) collapsed into `<details>`.
10
+ */
11
+ import type { Report } from '../types';
12
+ import { type ViewConfig } from './view';
13
+ export interface RenderMarkdownOptions {
14
+ /** Scores and counts only — no per-finding tables. */
15
+ summary?: boolean;
16
+ /** Expand internal (non-exposed) advisories instead of collapsing them. */
17
+ verbose?: boolean;
18
+ /** Heading text. Default `safegres`. */
19
+ title?: string;
20
+ /** Secondary planes to expand, by name or glob. Default: one summary table. */
21
+ planes?: string[];
22
+ /** Everything else the view layer selects. Beats the flags above. */
23
+ view?: ViewConfig;
24
+ }
25
+ export declare function renderMarkdown(report: Report, options?: RenderMarkdownOptions): string;