@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.
- package/README.md +825 -412
- package/adapters.d.ts +8 -0
- package/adapters.js +18 -0
- package/ast/helpers.d.ts +16 -0
- package/ast/helpers.js +40 -0
- package/ast/parse.d.ts +31 -0
- package/ast/parse.js +87 -0
- package/ast/walk.d.ts +27 -0
- package/ast/walk.js +79 -0
- package/callgraph/baseline.d.ts +28 -0
- package/callgraph/baseline.js +55 -0
- package/callgraph/extract.d.ts +93 -0
- package/callgraph/extract.js +340 -0
- package/callgraph/graph.d.ts +82 -0
- package/callgraph/graph.js +276 -0
- package/checks/anti-patterns.d.ts +53 -0
- package/checks/anti-patterns.js +247 -0
- package/checks/column-grants.d.ts +20 -0
- package/checks/column-grants.js +74 -0
- package/checks/coverage.d.ts +43 -0
- package/checks/coverage.js +110 -0
- package/checks/definer-function.d.ts +91 -0
- package/checks/definer-function.js +458 -0
- package/checks/definer-view.d.ts +167 -0
- package/checks/definer-view.js +392 -0
- package/checks/indexes.d.ts +82 -0
- package/checks/indexes.js +263 -0
- package/checks/lattice.d.ts +179 -0
- package/checks/lattice.js +487 -0
- package/checks/object-acls.d.ts +32 -0
- package/checks/object-acls.js +129 -0
- package/checks/policy-index.d.ts +78 -0
- package/checks/policy-index.js +349 -0
- package/checks/revocable-grants.d.ts +140 -0
- package/checks/revocable-grants.js +377 -0
- package/checks/rls-flags.d.ts +25 -0
- package/checks/rls-flags.js +82 -0
- package/checks/role-reach.d.ts +329 -0
- package/checks/role-reach.js +277 -0
- package/checks/role-trust.d.ts +45 -0
- package/checks/role-trust.js +91 -0
- package/checks/set-role.d.ts +21 -0
- package/checks/set-role.js +66 -0
- package/checks/stats.d.ts +52 -0
- package/checks/stats.js +192 -0
- package/checks/view-exposure.d.ts +68 -0
- package/checks/view-exposure.js +236 -0
- package/checks/view-writes.d.ts +88 -0
- package/checks/view-writes.js +350 -0
- package/ci/baseline.d.ts +104 -0
- package/ci/baseline.js +111 -0
- package/ci/github.d.ts +47 -0
- package/ci/github.js +197 -0
- package/cli/audit.d.ts +3 -0
- package/cli/audit.js +560 -0
- package/cli/baseline.d.ts +3 -0
- package/cli/baseline.js +104 -0
- package/cli/commands.d.ts +2 -0
- package/cli/commands.js +60 -0
- package/cli/doctor.d.ts +3 -0
- package/cli/doctor.js +72 -0
- package/cli/eval.d.ts +3 -0
- package/cli/eval.js +153 -0
- package/cli/print-config.d.ts +3 -0
- package/cli/print-config.js +54 -0
- package/cli/shared.d.ts +43 -0
- package/cli/shared.js +153 -0
- package/cli.d.ts +2 -0
- package/cli.js +69 -0
- package/commands/audit.d.ts +65 -0
- package/commands/audit.js +779 -0
- package/commands/doctor.d.ts +19 -0
- package/commands/doctor.js +181 -0
- package/commands/eval.d.ts +67 -0
- package/commands/eval.js +93 -0
- package/config/fingerprint.d.ts +40 -0
- package/config/fingerprint.js +71 -0
- package/config/loader.d.ts +44 -0
- package/config/loader.js +210 -0
- package/config/presets.d.ts +95 -0
- package/config/presets.js +327 -0
- package/config/resolve.d.ts +47 -0
- package/config/resolve.js +192 -0
- package/config/schema.d.ts +54 -0
- package/config/schema.js +269 -0
- package/config/types.d.ts +562 -0
- package/config/validate.d.ts +14 -0
- package/config/validate.js +125 -0
- package/corpus/README.md +83 -0
- package/corpus/bootstrap.sql +14 -0
- package/corpus/cases/01-anon-write-grant/case.json +26 -0
- package/corpus/cases/01-anon-write-grant/schema.sql +19 -0
- package/corpus/cases/02-grant-to-public/case.json +25 -0
- package/corpus/cases/02-grant-to-public/schema.sql +18 -0
- package/corpus/cases/03-rls-off-reachable-by-anon/case.json +30 -0
- package/corpus/cases/03-rls-off-reachable-by-anon/schema.sql +13 -0
- package/corpus/cases/04-permissive-write-policy/case.json +30 -0
- package/corpus/cases/04-permissive-write-policy/schema.sql +21 -0
- package/corpus/cases/05-public-read-policy/case.json +25 -0
- package/corpus/cases/05-public-read-policy/schema.sql +16 -0
- package/corpus/cases/06-update-without-with-check/case.json +25 -0
- package/corpus/cases/06-update-without-with-check/schema.sql +19 -0
- package/corpus/cases/07-rls-enabled-no-policies/case.json +29 -0
- package/corpus/cases/07-rls-enabled-no-policies/schema.sql +14 -0
- package/corpus/cases/08-select-grant-no-policy/case.json +25 -0
- package/corpus/cases/08-select-grant-no-policy/schema.sql +20 -0
- package/corpus/cases/09-write-grant-no-policy/case.json +24 -0
- package/corpus/cases/09-write-grant-no-policy/schema.sql +18 -0
- package/corpus/cases/10-rls-not-forced/case.json +24 -0
- package/corpus/cases/10-rls-not-forced/schema.sql +18 -0
- package/corpus/cases/11-session-user-in-policy/case.json +24 -0
- package/corpus/cases/11-session-user-in-policy/schema.sql +18 -0
- package/corpus/cases/12-volatile-function-in-policy/case.json +24 -0
- package/corpus/cases/12-volatile-function-in-policy/schema.sql +21 -0
- package/corpus/cases/13-security-definer-policy-wrapper/case.json +24 -0
- package/corpus/cases/13-security-definer-policy-wrapper/schema.sql +21 -0
- package/corpus/cases/14-dead-policy/case.json +24 -0
- package/corpus/cases/14-dead-policy/schema.sql +18 -0
- package/corpus/cases/15-unreachable-grant/case.json +24 -0
- package/corpus/cases/15-unreachable-grant/schema.sql +18 -0
- package/corpus/cases/16-anon-permissive-write-policy/case.json +34 -0
- package/corpus/cases/16-anon-permissive-write-policy/schema.sql +17 -0
- package/corpus/cases/17-foreign-key-without-index/case.json +24 -0
- package/corpus/cases/17-foreign-key-without-index/schema.sql +18 -0
- package/corpus/cases/18-policy-column-unindexed/case.json +24 -0
- package/corpus/cases/18-policy-column-unindexed/schema.sql +23 -0
- package/corpus/cases/19-policy-column-cast/case.json +24 -0
- package/corpus/cases/19-policy-column-cast/schema.sql +19 -0
- package/corpus/cases/20-stable-function-per-row/case.json +24 -0
- package/corpus/cases/20-stable-function-per-row/schema.sql +25 -0
- package/corpus/cases/21-table-without-primary-key/case.json +24 -0
- package/corpus/cases/21-table-without-primary-key/schema.sql +14 -0
- package/corpus/cases/22-redundant-index/case.json +24 -0
- package/corpus/cases/22-redundant-index/schema.sql +16 -0
- package/corpus/cases/23-tsvector-without-index/case.json +24 -0
- package/corpus/cases/23-tsvector-without-index/schema.sql +13 -0
- package/corpus/cases/24-anon-set-role-escalation/case.json +29 -0
- package/corpus/cases/24-anon-set-role-escalation/schema.sql +30 -0
- package/corpus/cases/25-definer-view-bypass/case.json +31 -0
- package/corpus/cases/25-definer-view-bypass/schema.sql +36 -0
- package/corpus/cases/26-invoker-view-no-bypass/case.json +31 -0
- package/corpus/cases/26-invoker-view-no-bypass/schema.sql +44 -0
- package/corpus/cases/27-definer-view-write/case.json +36 -0
- package/corpus/cases/27-definer-view-write/schema.sql +40 -0
- package/corpus/cases/28-invoker-view-no-write/case.json +31 -0
- package/corpus/cases/28-invoker-view-no-write/schema.sql +37 -0
- package/corpus/cases/29-rewrite-rule-bypass/case.json +36 -0
- package/corpus/cases/29-rewrite-rule-bypass/schema.sql +52 -0
- package/corpus/cases/30-instead-nothing-rule/case.json +31 -0
- package/corpus/cases/30-instead-nothing-rule/schema.sql +44 -0
- package/corpus/cases/31-matview-snapshot/case.json +32 -0
- package/corpus/cases/31-matview-snapshot/schema.sql +36 -0
- package/corpus/cases/32-matview-no-rls-no-bypass/case.json +30 -0
- package/corpus/cases/32-matview-no-rls-no-bypass/schema.sql +18 -0
- package/corpus/cases/33-leaky-filter-view/case.json +36 -0
- package/corpus/cases/33-leaky-filter-view/schema.sql +29 -0
- package/corpus/cases/34-barrier-view-no-leak/case.json +32 -0
- package/corpus/cases/34-barrier-view-no-leak/schema.sql +29 -0
- package/corpus/cases/35-column-grant-projection/case.json +27 -0
- package/corpus/cases/35-column-grant-projection/schema.sql +21 -0
- package/corpus/cases/35-policy-function-not-leakproof/case.json +24 -0
- package/corpus/cases/35-policy-function-not-leakproof/schema.sql +27 -0
- package/corpus/cases/36-column-grant-rls-mediated/case.json +27 -0
- package/corpus/cases/36-column-grant-rls-mediated/schema.sql +32 -0
- package/corpus/cases/36-policy-function-leakproof/case.json +24 -0
- package/corpus/cases/36-policy-function-leakproof/schema.sql +22 -0
- package/corpus/cases/37-sort-column-unindexed/case.json +24 -0
- package/corpus/cases/37-sort-column-unindexed/schema.sql +14 -0
- package/corpus/cases/37-unaudited-base-relation/case.json +30 -0
- package/corpus/cases/37-unaudited-base-relation/schema.sql +45 -0
- package/corpus/cases/38-foreign-key-with-index/case.json +22 -0
- package/corpus/cases/38-foreign-key-with-index/schema.sql +17 -0
- package/corpus/cases/38-invoker-view-unaudited-base/case.json +30 -0
- package/corpus/cases/38-invoker-view-unaudited-base/schema.sql +39 -0
- package/corpus/cases/39-definer-view-column-subset/case.json +30 -0
- package/corpus/cases/39-definer-view-column-subset/schema.sql +29 -0
- package/corpus/cases/39-policy-cast-with-expression-index/case.json +23 -0
- package/corpus/cases/39-policy-cast-with-expression-index/schema.sql +19 -0
- package/corpus/cases/40-definer-view-column-overreach/case.json +27 -0
- package/corpus/cases/40-definer-view-column-overreach/schema.sql +29 -0
- package/corpus/cases/40-stable-function-hoisted/case.json +23 -0
- package/corpus/cases/40-stable-function-hoisted/schema.sql +25 -0
- package/corpus/cases/41-index-prefix-not-redundant/case.json +21 -0
- package/corpus/cases/41-index-prefix-not-redundant/schema.sql +15 -0
- package/corpus/cases/41-unreadable-view-body/case.json +33 -0
- package/corpus/cases/41-unreadable-view-body/schema.sql +28 -0
- package/corpus/cases/42-invoker-view-unreadable-body/case.json +30 -0
- package/corpus/cases/42-invoker-view-unreadable-body/schema.sql +27 -0
- package/corpus/cases/42-search-column-indexed/case.json +21 -0
- package/corpus/cases/42-search-column-indexed/schema.sql +12 -0
- package/corpus/cases/43-anon-sequence-grant/case.json +27 -0
- package/corpus/cases/43-anon-sequence-grant/schema.sql +23 -0
- package/corpus/cases/44-serial-sequence-usage/case.json +27 -0
- package/corpus/cases/44-serial-sequence-usage/schema.sql +25 -0
- package/corpus/cases/45-anon-foreign-table/case.json +27 -0
- package/corpus/cases/45-anon-foreign-table/schema.sql +23 -0
- package/corpus/cases/46-unchecked-writable-view/case.json +41 -0
- package/corpus/cases/46-unchecked-writable-view/schema.sql +37 -0
- package/corpus/cases/47-checked-writable-view/case.json +37 -0
- package/corpus/cases/47-checked-writable-view/schema.sql +38 -0
- package/corpus/cases/48-definer-function-reach/case.json +38 -0
- package/corpus/cases/48-definer-function-reach/schema.sql +41 -0
- package/corpus/cases/49-invoker-function-no-reach/case.json +32 -0
- package/corpus/cases/49-invoker-function-no-reach/schema.sql +38 -0
- package/corpus/cases/50-instead-of-trigger-write/case.json +38 -0
- package/corpus/cases/50-instead-of-trigger-write/schema.sql +58 -0
- package/corpus/cases/51-invoker-trigger-no-write/case.json +33 -0
- package/corpus/cases/51-invoker-trigger-no-write/schema.sql +54 -0
- package/corpus/cases/52-revocable-execute-grant/case.json +30 -0
- package/corpus/cases/52-revocable-execute-grant/schema.sql +45 -0
- package/corpus/cases/53-policy-predicate-retains-execute/case.json +23 -0
- package/corpus/cases/53-policy-predicate-retains-execute/schema.sql +49 -0
- package/corpus/index.d.ts +79 -0
- package/corpus/index.js +125 -0
- package/esm/adapters.d.ts +8 -0
- package/esm/adapters.js +6 -0
- package/esm/ast/helpers.d.ts +16 -0
- package/esm/ast/helpers.js +36 -0
- package/esm/ast/parse.d.ts +31 -0
- package/esm/ast/parse.js +82 -0
- package/esm/ast/walk.d.ts +27 -0
- package/esm/ast/walk.js +72 -0
- package/esm/callgraph/baseline.d.ts +28 -0
- package/esm/callgraph/baseline.js +48 -0
- package/esm/callgraph/extract.d.ts +93 -0
- package/esm/callgraph/extract.js +333 -0
- package/esm/callgraph/graph.d.ts +82 -0
- package/esm/callgraph/graph.js +273 -0
- package/esm/checks/anti-patterns.d.ts +53 -0
- package/esm/checks/anti-patterns.js +240 -0
- package/esm/checks/column-grants.d.ts +20 -0
- package/esm/checks/column-grants.js +71 -0
- package/esm/checks/coverage.d.ts +43 -0
- package/esm/checks/coverage.js +104 -0
- package/esm/checks/definer-function.d.ts +91 -0
- package/esm/checks/definer-function.js +452 -0
- package/esm/checks/definer-view.d.ts +167 -0
- package/esm/checks/definer-view.js +382 -0
- package/esm/checks/indexes.d.ts +82 -0
- package/esm/checks/indexes.js +256 -0
- package/esm/checks/lattice.d.ts +179 -0
- package/esm/checks/lattice.js +475 -0
- package/esm/checks/object-acls.d.ts +32 -0
- package/esm/checks/object-acls.js +125 -0
- package/esm/checks/policy-index.d.ts +78 -0
- package/esm/checks/policy-index.js +342 -0
- package/esm/checks/revocable-grants.d.ts +140 -0
- package/esm/checks/revocable-grants.js +373 -0
- package/esm/checks/rls-flags.d.ts +25 -0
- package/esm/checks/rls-flags.js +77 -0
- package/esm/checks/role-reach.d.ts +329 -0
- package/esm/checks/role-reach.js +270 -0
- package/esm/checks/role-trust.d.ts +45 -0
- package/esm/checks/role-trust.js +86 -0
- package/esm/checks/set-role.d.ts +21 -0
- package/esm/checks/set-role.js +63 -0
- package/esm/checks/stats.d.ts +52 -0
- package/esm/checks/stats.js +184 -0
- package/esm/checks/view-exposure.d.ts +68 -0
- package/esm/checks/view-exposure.js +231 -0
- package/esm/checks/view-writes.d.ts +88 -0
- package/esm/checks/view-writes.js +344 -0
- package/esm/ci/baseline.d.ts +104 -0
- package/esm/ci/baseline.js +107 -0
- package/esm/ci/github.d.ts +47 -0
- package/esm/ci/github.js +161 -0
- package/esm/cli/audit.d.ts +3 -0
- package/esm/cli/audit.js +525 -0
- package/esm/cli/baseline.d.ts +3 -0
- package/esm/cli/baseline.js +102 -0
- package/esm/cli/commands.d.ts +2 -0
- package/esm/cli/commands.js +53 -0
- package/esm/cli/doctor.d.ts +3 -0
- package/esm/cli/doctor.js +67 -0
- package/esm/cli/eval.d.ts +3 -0
- package/esm/cli/eval.js +115 -0
- package/esm/cli/print-config.d.ts +3 -0
- package/esm/cli/print-config.js +52 -0
- package/esm/cli/shared.d.ts +43 -0
- package/esm/cli/shared.js +112 -0
- package/esm/cli.d.ts +2 -0
- package/esm/cli.js +67 -0
- package/esm/commands/audit.d.ts +65 -0
- package/esm/commands/audit.js +776 -0
- package/esm/commands/doctor.d.ts +19 -0
- package/esm/commands/doctor.js +178 -0
- package/esm/commands/eval.d.ts +67 -0
- package/esm/commands/eval.js +90 -0
- package/esm/config/fingerprint.d.ts +40 -0
- package/esm/config/fingerprint.js +68 -0
- package/esm/config/loader.d.ts +44 -0
- package/esm/config/loader.js +172 -0
- package/esm/config/presets.d.ts +95 -0
- package/esm/config/presets.js +324 -0
- package/esm/config/resolve.d.ts +47 -0
- package/esm/config/resolve.js +180 -0
- package/esm/config/schema.d.ts +54 -0
- package/esm/config/schema.js +265 -0
- package/esm/config/types.d.ts +562 -0
- package/esm/config/validate.d.ts +14 -0
- package/esm/config/validate.js +122 -0
- package/esm/corpus/index.d.ts +79 -0
- package/esm/corpus/index.js +85 -0
- package/esm/exposure/adapters.d.ts +152 -0
- package/esm/exposure/adapters.js +463 -0
- package/esm/exposure/planes.d.ts +59 -0
- package/esm/exposure/planes.js +144 -0
- package/esm/exposure/reach.d.ts +78 -0
- package/esm/exposure/reach.js +105 -0
- package/esm/exposure/routines.d.ts +36 -0
- package/esm/exposure/routines.js +54 -0
- package/esm/index.d.ts +96 -0
- package/esm/index.js +57 -6
- package/esm/lint/index.d.ts +11 -0
- package/esm/lint/index.js +10 -0
- package/esm/perf/baseline.d.ts +40 -0
- package/esm/perf/baseline.js +83 -0
- package/esm/perf/explain.d.ts +46 -0
- package/esm/perf/explain.js +201 -0
- package/esm/pg/acl.d.ts +72 -0
- package/esm/pg/acl.js +186 -0
- package/esm/pg/behaviors.d.ts +114 -0
- package/esm/pg/behaviors.js +206 -0
- package/esm/pg/exposure.d.ts +74 -0
- package/esm/pg/exposure.js +198 -0
- package/esm/pg/functions.d.ts +52 -0
- package/esm/pg/functions.js +128 -0
- package/esm/pg/indexes.d.ts +192 -0
- package/esm/pg/indexes.js +395 -0
- package/esm/pg/introspect.d.ts +134 -0
- package/esm/pg/introspect.js +274 -0
- package/esm/pg/objects.d.ts +37 -0
- package/esm/pg/objects.js +108 -0
- package/esm/pg/paths.d.ts +114 -0
- package/esm/pg/paths.js +159 -0
- package/esm/pg/proc.d.ts +23 -0
- package/esm/pg/proc.js +55 -0
- package/esm/pg/reach-inputs.d.ts +47 -0
- package/esm/pg/reach-inputs.js +133 -0
- package/esm/pg/roles.d.ts +28 -0
- package/esm/pg/roles.js +50 -0
- package/esm/pg/stats.d.ts +65 -0
- package/esm/pg/stats.js +129 -0
- package/esm/pgpm-test.d.ts +22 -0
- package/esm/pgpm-test.js +39 -0
- package/esm/report/callgraph.d.ts +9 -0
- package/esm/report/callgraph.js +74 -0
- package/esm/report/compare.d.ts +143 -0
- package/esm/report/compare.js +195 -0
- package/esm/report/github.d.ts +74 -0
- package/esm/report/github.js +290 -0
- package/esm/report/json.d.ts +4 -0
- package/esm/report/json.js +3 -0
- package/esm/report/markdown.d.ts +25 -0
- package/esm/report/markdown.js +352 -0
- package/esm/report/pretty.d.ts +14 -0
- package/esm/report/pretty.js +318 -0
- package/esm/report/sarif.d.ts +40 -0
- package/esm/report/sarif.js +189 -0
- package/esm/report/view.d.ts +82 -0
- package/esm/report/view.js +126 -0
- package/esm/rules/registry.d.ts +66 -0
- package/esm/rules/registry.js +562 -0
- package/esm/score/score.d.ts +84 -0
- package/esm/score/score.js +233 -0
- package/esm/score/scorecards.d.ts +68 -0
- package/esm/score/scorecards.js +157 -0
- package/esm/types.d.ts +292 -0
- package/esm/types.js +26 -0
- package/esm/version.d.ts +8 -0
- package/esm/version.js +9 -0
- package/exposure/adapters.d.ts +152 -0
- package/exposure/adapters.js +468 -0
- package/exposure/planes.d.ts +59 -0
- package/exposure/planes.js +151 -0
- package/exposure/reach.d.ts +78 -0
- package/exposure/reach.js +109 -0
- package/exposure/routines.d.ts +36 -0
- package/exposure/routines.js +57 -0
- package/index.d.ts +96 -6
- package/index.js +229 -6
- package/lint/index.d.ts +11 -0
- package/lint/index.js +19 -0
- package/package.json +54 -48
- package/perf/baseline.d.ts +40 -0
- package/perf/baseline.js +92 -0
- package/perf/explain.d.ts +46 -0
- package/perf/explain.js +204 -0
- package/pg/acl.d.ts +72 -0
- package/pg/acl.js +191 -0
- package/pg/behaviors.d.ts +114 -0
- package/pg/behaviors.js +217 -0
- package/pg/exposure.d.ts +74 -0
- package/pg/exposure.js +205 -0
- package/pg/functions.d.ts +52 -0
- package/pg/functions.js +131 -0
- package/pg/indexes.d.ts +192 -0
- package/pg/indexes.js +400 -0
- package/pg/introspect.d.ts +134 -0
- package/pg/introspect.js +280 -0
- package/pg/objects.d.ts +37 -0
- package/pg/objects.js +111 -0
- package/pg/paths.d.ts +114 -0
- package/pg/paths.js +166 -0
- package/pg/proc.d.ts +23 -0
- package/pg/proc.js +58 -0
- package/pg/reach-inputs.d.ts +47 -0
- package/pg/reach-inputs.js +136 -0
- package/pg/roles.d.ts +28 -0
- package/pg/roles.js +54 -0
- package/pg/stats.d.ts +65 -0
- package/pg/stats.js +133 -0
- package/pgpm-test.d.ts +22 -0
- package/pgpm-test.js +42 -0
- package/report/callgraph.d.ts +9 -0
- package/report/callgraph.js +81 -0
- package/report/compare.d.ts +143 -0
- package/report/compare.js +205 -0
- package/report/github.d.ts +74 -0
- package/report/github.js +333 -0
- package/report/json.d.ts +4 -0
- package/report/json.js +6 -0
- package/report/markdown.d.ts +25 -0
- package/report/markdown.js +355 -0
- package/report/pretty.d.ts +14 -0
- package/report/pretty.js +324 -0
- package/report/sarif.d.ts +40 -0
- package/report/sarif.js +193 -0
- package/report/view.d.ts +82 -0
- package/report/view.js +132 -0
- package/rules/registry.d.ts +66 -0
- package/rules/registry.js +569 -0
- package/schema/safegres.schema.json +1119 -0
- package/score/score.d.ts +84 -0
- package/score/score.js +238 -0
- package/score/scorecards.d.ts +68 -0
- package/score/scorecards.js +162 -0
- package/types.d.ts +292 -0
- package/types.js +32 -0
- package/version.d.ts +8 -0
- package/version.js +12 -0
- package/LICENSE +0 -23
- package/admin.d.ts +0 -26
- package/admin.js +0 -182
- package/connect.d.ts +0 -19
- package/connect.js +0 -83
- package/dist/README.md +0 -557
- package/dist/package.json +0 -72
- package/esm/admin.js +0 -178
- package/esm/connect.js +0 -78
- package/esm/manager.js +0 -136
- package/esm/roles.js +0 -32
- package/esm/seed/adapters.js +0 -23
- package/esm/seed/csv.js +0 -44
- package/esm/seed/index.js +0 -16
- package/esm/seed/json.js +0 -18
- package/esm/seed/launchql.js +0 -19
- package/esm/seed/sqitch.js +0 -17
- package/esm/stream.js +0 -43
- package/esm/test-client.js +0 -150
- package/manager.d.ts +0 -25
- package/manager.js +0 -140
- package/roles.d.ts +0 -17
- package/roles.js +0 -38
- package/seed/adapters.d.ts +0 -4
- package/seed/adapters.js +0 -28
- package/seed/csv.d.ts +0 -9
- package/seed/csv.js +0 -49
- package/seed/index.d.ts +0 -16
- package/seed/index.js +0 -33
- package/seed/json.d.ts +0 -6
- package/seed/json.js +0 -21
- package/seed/launchql.d.ts +0 -2
- package/seed/launchql.js +0 -22
- package/seed/sqitch.d.ts +0 -2
- package/seed/sqitch.js +0 -20
- package/seed/types.d.ts +0 -13
- package/stream.d.ts +0 -2
- package/stream.js +0 -46
- package/test-client.d.ts +0 -49
- package/test-client.js +0 -154
- /package/{seed → config}/types.js +0 -0
- /package/esm/{seed → config}/types.js +0 -0
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
import type { ExposureAdapter } from '../exposure/adapters';
|
|
2
|
+
import type { Dimension, Direction, Severity } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* `'off'` disables a rule; a severity retunes it; `[severity, options]`
|
|
5
|
+
* reserves room for rule-specific options (forward-compatible).
|
|
6
|
+
*/
|
|
7
|
+
export type RuleSetting = 'off' | Severity | [Severity, Record<string, unknown>];
|
|
8
|
+
/**
|
|
9
|
+
* Rule settings keyed by rule code or prefix wildcard (`A*`, `P*`, `*`).
|
|
10
|
+
* Exact codes always win over wildcards.
|
|
11
|
+
*/
|
|
12
|
+
export type RulesConfig = Record<string, RuleSetting>;
|
|
13
|
+
/** Per-scope retuning, ESLint `overrides`-style. */
|
|
14
|
+
export interface OverrideEntry {
|
|
15
|
+
/**
|
|
16
|
+
* Glob patterns matched against the qualified `schema.table` name
|
|
17
|
+
* (`*` matches any run of characters), e.g. `public.audit_log`, `metrics.*`.
|
|
18
|
+
*/
|
|
19
|
+
tables: string[];
|
|
20
|
+
rules: RulesConfig;
|
|
21
|
+
}
|
|
22
|
+
export type Grade = 'A+' | 'A' | 'B' | 'C' | 'D' | 'F';
|
|
23
|
+
/**
|
|
24
|
+
* The exposure surface: what is actually reachable through the exposed APIs.
|
|
25
|
+
* Findings on non-exposed schemas contribute nothing to the score — they are
|
|
26
|
+
* reported as internal advisories. When no surface is configured or
|
|
27
|
+
* resolvable, the whole database is assumed reachable, a W1 warning is
|
|
28
|
+
* emitted, and the score is capped.
|
|
29
|
+
*/
|
|
30
|
+
export interface ExposureConfig {
|
|
31
|
+
/**
|
|
32
|
+
* How to resolve the surface:
|
|
33
|
+
* - `static` (default): use `schemas` / `roles` as given.
|
|
34
|
+
* - `constructive`: introspect the Constructive routing plane
|
|
35
|
+
* (`routing_public.apis` → `api_schemas` → `metaschema_public.schema`,
|
|
36
|
+
* plus the platform plane) to discover exposed schemas and API roles.
|
|
37
|
+
*
|
|
38
|
+
* - `postgraphile`: contribute no planes, but read behavior tags so the
|
|
39
|
+
* planes another resolver or `schemas` establishes are narrowed from
|
|
40
|
+
* "every relation in the schema" to the relations the generated API can
|
|
41
|
+
* address. Pair it with `schemas`, or use it alone for the reach only.
|
|
42
|
+
*
|
|
43
|
+
* Equivalent to listing the corresponding built-in in `adapters`.
|
|
44
|
+
*/
|
|
45
|
+
resolver?: 'static' | 'constructive' | 'postgraphile';
|
|
46
|
+
/**
|
|
47
|
+
* Exposure adapters: objects implementing `ExposureAdapter`, or the name of
|
|
48
|
+
* a built-in (`'constructive'`, `'postgraphile'`). An adapter whose `detect()` succeeds
|
|
49
|
+
* contributes planes; static `schemas`/`roles` extend, never replace, what
|
|
50
|
+
* it found. Adapters are values, not module names — a custom one is an
|
|
51
|
+
* object you construct, and nothing is resolved by package name.
|
|
52
|
+
*/
|
|
53
|
+
adapters?: Array<string | ExposureAdapter>;
|
|
54
|
+
/** Schemas reachable from the exposed APIs (static resolver). */
|
|
55
|
+
schemas?: string[];
|
|
56
|
+
/** Roles reachable from the API edge (static resolver). */
|
|
57
|
+
roles?: string[];
|
|
58
|
+
/**
|
|
59
|
+
* The subset of `roles` an unauthenticated caller arrives as. Adapters
|
|
60
|
+
* resolve this themselves (`apis.anon_role`, `pgrst.db_anon_role`, ...);
|
|
61
|
+
* set it only for a surface you are declaring statically.
|
|
62
|
+
*/
|
|
63
|
+
anonRoles?: string[];
|
|
64
|
+
/** Name of the primary plane. Default `api`. */
|
|
65
|
+
name?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Let adapters narrow a plane's reach from its schemas to the relations the
|
|
68
|
+
* generated API can actually address (`postgraphile` reads behavior tags for
|
|
69
|
+
* this). Default `true`; an adapter that cannot answer changes nothing.
|
|
70
|
+
*
|
|
71
|
+
* Set `false` to grade every relation in an exposed schema as exposed, which
|
|
72
|
+
* is the safer reading if you do not trust your behavior declarations.
|
|
73
|
+
*/
|
|
74
|
+
reach?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Additional access planes to grade: the ways into the database that are
|
|
77
|
+
* not the declared API. Each is scored on the security axis with the same
|
|
78
|
+
* model, reported alongside the primary plane, and — unless `failOn.planes`
|
|
79
|
+
* says otherwise — gates nothing.
|
|
80
|
+
*/
|
|
81
|
+
planes?: PlaneConfig[];
|
|
82
|
+
}
|
|
83
|
+
/** What kind of access path a plane describes. */
|
|
84
|
+
export type PlaneKind = 'api' | 'role' | 'schema';
|
|
85
|
+
/**
|
|
86
|
+
* One graded access plane. `api`/`schema` planes are a set of schemas; a
|
|
87
|
+
* `role` plane is whatever its roles can effectively reach (direct grants,
|
|
88
|
+
* grants TO PUBLIC, and role inheritance), so it never has to be kept in
|
|
89
|
+
* sync with a schema list by hand.
|
|
90
|
+
*/
|
|
91
|
+
export interface PlaneConfig {
|
|
92
|
+
/** Plane identifier, e.g. `api`, `direct:app`, `internal`. */
|
|
93
|
+
name: string;
|
|
94
|
+
/** Default: `role` when `roles` is set and `schemas` is not, else `schema`. */
|
|
95
|
+
kind?: PlaneKind;
|
|
96
|
+
/**
|
|
97
|
+
* Make this plane the headline score (`report.score`). At most one plane
|
|
98
|
+
* may claim it; declaring two is a configuration error rather than a
|
|
99
|
+
* silent pick. Default: the declared API surface is primary.
|
|
100
|
+
*/
|
|
101
|
+
primary?: boolean;
|
|
102
|
+
schemas?: string[];
|
|
103
|
+
roles?: string[];
|
|
104
|
+
/** The subset of `roles` reachable without authenticating. */
|
|
105
|
+
anonRoles?: string[];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Declared-public surface: intent, stated in config. Open reads on declared
|
|
109
|
+
* tables are acknowledged — reported as info and excluded from the score.
|
|
110
|
+
* Open reads anywhere else stay findings, even in `*_public`-named schemas;
|
|
111
|
+
* naming is never treated as intent.
|
|
112
|
+
*/
|
|
113
|
+
export interface PublicConfig {
|
|
114
|
+
/**
|
|
115
|
+
* Glob patterns matched against the qualified `schema.table` name
|
|
116
|
+
* (`*` matches any run of characters) for tables whose open SELECT
|
|
117
|
+
* (`USING (true)`) policies are by design, e.g. reference/pricing tables
|
|
118
|
+
* or a deliberate public directory.
|
|
119
|
+
*/
|
|
120
|
+
read?: string[];
|
|
121
|
+
}
|
|
122
|
+
export interface ScoringConfig {
|
|
123
|
+
/**
|
|
124
|
+
* Scoring model:
|
|
125
|
+
* - `density` (default): severity-weighted findings per exposed table with
|
|
126
|
+
* exponential falloff — does not saturate on large schemas.
|
|
127
|
+
* - `weighted`: legacy flat deductions with a per-rule cap.
|
|
128
|
+
*/
|
|
129
|
+
model?: 'density' | 'weighted';
|
|
130
|
+
/** Points deducted per finding of each severity. */
|
|
131
|
+
weights?: Partial<Record<Severity, number>>;
|
|
132
|
+
/** Per-rule weight override — beats the severity weight. */
|
|
133
|
+
perRuleWeights?: Record<string, number>;
|
|
134
|
+
/** Cap on total deduction any single rule can contribute (weighted model). */
|
|
135
|
+
maxDeductionPerRule?: number;
|
|
136
|
+
/**
|
|
137
|
+
* Cap on any single rule's contribution (density model), as a fraction of
|
|
138
|
+
* the points that would take the score to F on their own. Default 0.5 — one
|
|
139
|
+
* rule at its cap costs two grade bands, and an F still takes breadth.
|
|
140
|
+
*
|
|
141
|
+
* The density curve has no natural ceiling, so before this a rule's weight
|
|
142
|
+
* and its *fan-out* were indistinguishable: L19 emitting one finding per
|
|
143
|
+
* (relation × function) pair took a real audit from A+ to F on one severity
|
|
144
|
+
* notch. `false` removes the cap.
|
|
145
|
+
*/
|
|
146
|
+
maxRuleDensity?: number | false;
|
|
147
|
+
/**
|
|
148
|
+
* Multiplier applied to fail-closed findings' weights (density model).
|
|
149
|
+
* Default 0 — denied-at-runtime hygiene findings don't reduce the score.
|
|
150
|
+
*/
|
|
151
|
+
failClosedWeight?: number;
|
|
152
|
+
/** Density falloff constant (density model). Default 0.17. */
|
|
153
|
+
densityK?: number;
|
|
154
|
+
/**
|
|
155
|
+
* Maximum score when no exposure surface is configured/resolvable.
|
|
156
|
+
* Default 80. `false` disables the cap.
|
|
157
|
+
*/
|
|
158
|
+
unknownExposureCap?: number | false;
|
|
159
|
+
/** Any finding at/above this severity caps the grade (e.g. 'critical' -> 'C'). */
|
|
160
|
+
floorOnCritical?: Grade | false;
|
|
161
|
+
/** Minimum score for each grade; anything below the lowest is 'F'. */
|
|
162
|
+
gradeBands?: Partial<Record<Exclude<Grade, 'F'>, number>>;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* A named score over a slice of the findings: a selector plus the weighting
|
|
166
|
+
* to grade what it selects with. Every scoring key is available per card, so
|
|
167
|
+
* a scorecard is a full `ScoringConfig` with a question attached.
|
|
168
|
+
*
|
|
169
|
+
* The point is that "how secure is this database" is not one question. A
|
|
170
|
+
* platform team gates on what `anonymous` reaches; an application team gates
|
|
171
|
+
* on house style; a compliance reviewer wants the number that no preset
|
|
172
|
+
* softened. Collapsing those into a single grade means at least two of them
|
|
173
|
+
* are reading a number that does not answer their question — and the first
|
|
174
|
+
* time it disagrees with their judgement, they stop reading it at all.
|
|
175
|
+
*
|
|
176
|
+
* ```jsonc
|
|
177
|
+
* "scorecards": {
|
|
178
|
+
* "anon-surface": {
|
|
179
|
+
* "description": "What an unauthenticated caller reaches.",
|
|
180
|
+
* "select": { "roles": ["anonymous"], "direction": "fail-open" },
|
|
181
|
+
* "perRuleWeights": { "L19": 10 },
|
|
182
|
+
* "floorOnCritical": "C"
|
|
183
|
+
* },
|
|
184
|
+
* "sql-conventions": { "select": { "rules": ["C*"], "exposure": "all" } }
|
|
185
|
+
* }
|
|
186
|
+
* ```
|
|
187
|
+
*
|
|
188
|
+
* Findings are never filtered by a scorecard — only *scored* by one. The
|
|
189
|
+
* report always carries every finding, so no configuration of this block can
|
|
190
|
+
* hide anything; it can only decide what a given number is about.
|
|
191
|
+
*/
|
|
192
|
+
export interface ScorecardConfig extends ScoringConfig {
|
|
193
|
+
/** Heading for reports. Defaults to the config key. */
|
|
194
|
+
title?: string;
|
|
195
|
+
/** What decision this score informs. Rendered with it. */
|
|
196
|
+
description?: string;
|
|
197
|
+
/** Which findings it grades. An empty selector grades what the headline does. */
|
|
198
|
+
select?: ScorecardSelector;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Which findings a scorecard grades. Every clause narrows; omitting one
|
|
202
|
+
* means "don't care", and an empty selector is the headline's own slice
|
|
203
|
+
* (exposed, non-acknowledged, security-dimension).
|
|
204
|
+
*/
|
|
205
|
+
export interface ScorecardSelector {
|
|
206
|
+
/** Rule codes or `C*` prefix wildcards to include. Default: all. */
|
|
207
|
+
rules?: string[];
|
|
208
|
+
/** Rule codes or wildcards to drop after `rules` has selected. */
|
|
209
|
+
exclude?: string[];
|
|
210
|
+
/** `security` (default), `perf`, or `all` — the two axes in one number. */
|
|
211
|
+
dimension?: Dimension | 'all';
|
|
212
|
+
/** Only findings about these roles (the finding's role, grantee, or reach context). */
|
|
213
|
+
roles?: string[];
|
|
214
|
+
/** Only findings reachable on these access planes. */
|
|
215
|
+
planes?: string[];
|
|
216
|
+
/** Only findings in these schemas. */
|
|
217
|
+
schemas?: string[];
|
|
218
|
+
/** `fail-open` leaks, `fail-closed` denials, or `any`. Default: any. */
|
|
219
|
+
direction?: Direction | 'any';
|
|
220
|
+
/** Drop findings below this severity before scoring. */
|
|
221
|
+
minSeverity?: Severity;
|
|
222
|
+
/**
|
|
223
|
+
* `exposed` (default) grades only what the API surface reaches; `all`
|
|
224
|
+
* ignores exposure entirely — the honest, database-to-database number.
|
|
225
|
+
*/
|
|
226
|
+
exposure?: 'exposed' | 'all';
|
|
227
|
+
/** `include` grades acknowledged findings too. Default: skip them. */
|
|
228
|
+
acknowledged?: 'skip' | 'include';
|
|
229
|
+
/**
|
|
230
|
+
* `configured` (default) uses the severities this config resolved;
|
|
231
|
+
* `declared` uses each rule's registry default, so a preset that quiets a
|
|
232
|
+
* rule cannot quiet the score that is supposed to catch it.
|
|
233
|
+
*/
|
|
234
|
+
severities?: 'configured' | 'declared';
|
|
235
|
+
/**
|
|
236
|
+
* Density denominator: `exposed` relations (default) or `all` of them.
|
|
237
|
+
* A card that ignores exposure should normalize by everything, or it
|
|
238
|
+
* divides a wider numerator by a narrower denominator.
|
|
239
|
+
*/
|
|
240
|
+
denominator?: 'exposed' | 'all';
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* The optional performance dimension: index-hygiene and policy-cost rules
|
|
244
|
+
* (`X*`, plus P1/P1b), scored on their own axis against the same exposure
|
|
245
|
+
* surface. Off by default — `safegres perf` / `--perf` / `enabled: true`.
|
|
246
|
+
*/
|
|
247
|
+
export interface PerfConfig {
|
|
248
|
+
/** Collect and score perf findings without passing `--perf`. */
|
|
249
|
+
enabled?: boolean;
|
|
250
|
+
/**
|
|
251
|
+
* Rule settings for perf-dimension codes only. Applied on top of the
|
|
252
|
+
* top-level `rules`; naming a security rule here is a config error.
|
|
253
|
+
*/
|
|
254
|
+
rules?: RulesConfig;
|
|
255
|
+
/**
|
|
256
|
+
* Glob patterns matched against the qualified `schema.table` name for
|
|
257
|
+
* tables whose perf findings are intentional (cold audit logs, tiny
|
|
258
|
+
* lookup tables the planner will seq-scan anyway). Acknowledged findings
|
|
259
|
+
* are reported as info and excluded from the perf score.
|
|
260
|
+
*/
|
|
261
|
+
ignore?: string[];
|
|
262
|
+
/** Scoring settings for the perf axis (defaults mirror the security score). */
|
|
263
|
+
scoring?: PerfScoringConfig;
|
|
264
|
+
/** Runtime statistics (`--stats`, `S*`). Off unless enabled here or by flag. */
|
|
265
|
+
stats?: PerfStatsConfig;
|
|
266
|
+
/** Planner proof (`--explain`). Off unless enabled here or by flag. */
|
|
267
|
+
explain?: PerfExplainConfig;
|
|
268
|
+
/**
|
|
269
|
+
* Baseline of accepted perf debt. Present → the run diffs against it, the
|
|
270
|
+
* same as `--perf-baseline`. Writing one stays a flag (`--write-perf-baseline`):
|
|
271
|
+
* accepting debt is an act, not a setting.
|
|
272
|
+
*/
|
|
273
|
+
baseline?: string;
|
|
274
|
+
/** Exit non-zero on a perf finding that isn't in the baseline. */
|
|
275
|
+
failOnNew?: boolean;
|
|
276
|
+
/** Access-path classification, which decides whether X1 applies to a key. */
|
|
277
|
+
paths?: PerfPathsConfig;
|
|
278
|
+
}
|
|
279
|
+
export interface PerfPathsConfig {
|
|
280
|
+
/**
|
|
281
|
+
* Collect access-path signals for every foreign key. Default true. Signals
|
|
282
|
+
* are reported, and by default change no finding and no score; set false to
|
|
283
|
+
* skip the introspection entirely.
|
|
284
|
+
*/
|
|
285
|
+
infer?: boolean;
|
|
286
|
+
/**
|
|
287
|
+
* Write-once pointers a table needs before the `config-record` signal fires.
|
|
288
|
+
* Default 2. Raise it for a narrower signal.
|
|
289
|
+
*/
|
|
290
|
+
minPointers?: number;
|
|
291
|
+
/**
|
|
292
|
+
* What X1 does with a key whose only evidence is shape — it looks like a
|
|
293
|
+
* write-once provisioning pointer, but nothing has proven the path is
|
|
294
|
+
* unreachable.
|
|
295
|
+
*
|
|
296
|
+
* - `report` (default) — the finding stands, with the signals attached.
|
|
297
|
+
* - `demote` — the finding drops to `info`, so it is read rather than gated
|
|
298
|
+
* on and contributes nothing to the score.
|
|
299
|
+
* - `suppress` — no finding. Only defensible once you know the generated API
|
|
300
|
+
* does not expose these relations; a shape is not a proof.
|
|
301
|
+
*/
|
|
302
|
+
onWriteOncePointer?: 'report' | 'demote' | 'suppress';
|
|
303
|
+
}
|
|
304
|
+
export interface PerfScoringConfig extends ScoringConfig {
|
|
305
|
+
/**
|
|
306
|
+
* Whether runtime-statistics findings (`S*`) count toward the perf score.
|
|
307
|
+
* Default true — asking for `--stats` is the opt-in. Set false to keep the
|
|
308
|
+
* grade purely deterministic and read the `S*` findings as advisories.
|
|
309
|
+
*/
|
|
310
|
+
includeStats?: boolean;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Thresholds for the runtime-statistics rules. Every one is a floor: below
|
|
314
|
+
* it the workload hasn't said enough for the finding to mean anything.
|
|
315
|
+
*/
|
|
316
|
+
export interface PerfStatsConfig {
|
|
317
|
+
/** Collect and check runtime statistics without passing `--stats`. */
|
|
318
|
+
enabled?: boolean;
|
|
319
|
+
/** Ignore tables with fewer live rows than this. Default 1000. */
|
|
320
|
+
minRows?: number;
|
|
321
|
+
/** S1 fires when sequential scans exceed index scans by this factor. Default 10. */
|
|
322
|
+
seqScanRatio?: number;
|
|
323
|
+
/** S2 ignores indexes smaller than this many bytes. Default 1048576 (1 MiB). */
|
|
324
|
+
minIndexBytes?: number;
|
|
325
|
+
/** S3 fires above this dead/live tuple ratio. Default 0.2. */
|
|
326
|
+
deadTupleRatio?: number;
|
|
327
|
+
/** S4 fires for statements at or above this share of total time. Default 0.05. */
|
|
328
|
+
minTimeShare?: number;
|
|
329
|
+
/** S4 reports at most this many statements. Default 5. */
|
|
330
|
+
topStatements?: number;
|
|
331
|
+
}
|
|
332
|
+
export interface PerfExplainConfig {
|
|
333
|
+
/** Probe findings with EXPLAIN without passing `--explain`. */
|
|
334
|
+
enabled?: boolean;
|
|
335
|
+
/**
|
|
336
|
+
* Below this planner row estimate a sequential scan is the right plan, so a
|
|
337
|
+
* probe can refute a finding but never confirm one. Default 1000.
|
|
338
|
+
*/
|
|
339
|
+
minRows?: number;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Extension objects are a database's `node_modules`: they live in the same
|
|
343
|
+
* catalog and scan like anything else, but they are the extension author's
|
|
344
|
+
* to secure and tune, and altering them breaks `pg_dump` and upgrades.
|
|
345
|
+
*/
|
|
346
|
+
export interface ExtensionsConfig {
|
|
347
|
+
/**
|
|
348
|
+
* Skip relations an extension owns (`pg_depend.deptype = 'e'`) and their
|
|
349
|
+
* partitions. Default `true`. Set `false` to audit them anyway — useful
|
|
350
|
+
* when auditing an extension itself.
|
|
351
|
+
*/
|
|
352
|
+
skipOwned?: boolean;
|
|
353
|
+
/**
|
|
354
|
+
* Extension names whose *schemas* are skipped wholesale, for objects an
|
|
355
|
+
* extension creates at runtime and never registers as dependencies.
|
|
356
|
+
* `pg_partman` is the motivating case: its child partitions and templates
|
|
357
|
+
* carry no dependency on the extension, so ownership alone misses them.
|
|
358
|
+
* Unknown or uninstalled names are ignored.
|
|
359
|
+
*/
|
|
360
|
+
ignore?: string[];
|
|
361
|
+
}
|
|
362
|
+
export interface FailOnConfig {
|
|
363
|
+
/** Exit non-zero if any finding is at/above this severity. */
|
|
364
|
+
severity?: Severity;
|
|
365
|
+
/** Exit non-zero if the score is below this value (0-100). */
|
|
366
|
+
score?: number;
|
|
367
|
+
/** Exit non-zero if the grade is below this letter. */
|
|
368
|
+
grade?: Grade;
|
|
369
|
+
/** Exit non-zero if the perf score is below this value (0-100). */
|
|
370
|
+
perfScore?: number;
|
|
371
|
+
/** Exit non-zero if the perf grade is below this letter. */
|
|
372
|
+
perfGrade?: Grade;
|
|
373
|
+
/**
|
|
374
|
+
* Per-plane gates, keyed by plane name. Secondary planes gate nothing by
|
|
375
|
+
* default: an internal role legitimately reaches internal tables, so its
|
|
376
|
+
* plane scores worse than the API's by construction and gating it at parity
|
|
377
|
+
* would only force the plane to be deleted. A floor (`{ grade: 'D' }`) is
|
|
378
|
+
* the useful shape — the direct-connection surface may be a D, but it may
|
|
379
|
+
* not become an F.
|
|
380
|
+
*/
|
|
381
|
+
planes?: Record<string, PlaneFailOnConfig>;
|
|
382
|
+
/**
|
|
383
|
+
* Per-scorecard gates, keyed by scorecard name. This is where a team's own
|
|
384
|
+
* question becomes its own build failure — `{ "anon-surface": { "grade": "A" } }`
|
|
385
|
+
* gates on that and nothing else.
|
|
386
|
+
*/
|
|
387
|
+
scorecards?: Record<string, PlaneFailOnConfig>;
|
|
388
|
+
}
|
|
389
|
+
export interface PlaneFailOnConfig {
|
|
390
|
+
/** Exit non-zero if the plane's score is below this value (0-100). */
|
|
391
|
+
score?: number;
|
|
392
|
+
/** Exit non-zero if the plane's grade is below this letter. */
|
|
393
|
+
grade?: Grade;
|
|
394
|
+
}
|
|
395
|
+
/** Which scores and sections a rendered report shows. */
|
|
396
|
+
/**
|
|
397
|
+
* The database under audit. A repository that always audits the same thing —
|
|
398
|
+
* a pgpm workspace deployed into an ephemeral database — should say so once,
|
|
399
|
+
* in the file, rather than in every invocation.
|
|
400
|
+
*/
|
|
401
|
+
export interface SourceConfig {
|
|
402
|
+
/**
|
|
403
|
+
* Deploy the pgpm workspace or module at this path (relative to the config
|
|
404
|
+
* file) into an ephemeral test database and audit that. Equivalent to
|
|
405
|
+
* `--pgpm <dir>`; requires the optional peer dependency `pgsql-test`.
|
|
406
|
+
* A connection named on the command line (`--connection`, `--database`,
|
|
407
|
+
* `--host`, `--port`) wins: the same config then audits that database.
|
|
408
|
+
*/
|
|
409
|
+
pgpm?: string;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Files one run writes. Paths are relative to the config file, and the
|
|
413
|
+
* directories are created as needed: the point is that a CI job is
|
|
414
|
+
* `safegres audit`, with the artifact list versioned alongside the rules.
|
|
415
|
+
*/
|
|
416
|
+
export interface OutputsConfig {
|
|
417
|
+
/**
|
|
418
|
+
* Write the whole set into one directory as `safegres.json`, `safegres.md`
|
|
419
|
+
* and `safegres.sarif`. The usual case, and nobody has to remember three
|
|
420
|
+
* paths; the keys below still override an individual file.
|
|
421
|
+
*/
|
|
422
|
+
dir?: string;
|
|
423
|
+
json?: string;
|
|
424
|
+
markdown?: string;
|
|
425
|
+
sarif?: string;
|
|
426
|
+
/** Root scanned to resolve SARIF findings to their SQL source lines. */
|
|
427
|
+
sarifSources?: string;
|
|
428
|
+
/** Aggregate-only snapshot, for a later run's `compare`. */
|
|
429
|
+
snapshot?: string;
|
|
430
|
+
/** The rendered sticky PR comment, for a workflow that posts it itself. */
|
|
431
|
+
githubComment?: string;
|
|
432
|
+
}
|
|
433
|
+
export interface CallGraphConfig {
|
|
434
|
+
/** Build the call-graph audit without passing `--call-graph`. */
|
|
435
|
+
enabled?: boolean;
|
|
436
|
+
/** Baseline of accepted trust boundaries; enables the diff. */
|
|
437
|
+
baseline?: string;
|
|
438
|
+
/** Exit non-zero on a boundary that isn't in the baseline. */
|
|
439
|
+
failOnNew?: boolean;
|
|
440
|
+
}
|
|
441
|
+
export interface ReportConfig {
|
|
442
|
+
/**
|
|
443
|
+
* Planes to render, by name or glob (`primary`, `*`, `direct:*`). Default:
|
|
444
|
+
* the primary plane in full, secondaries as a one-line advisory.
|
|
445
|
+
*/
|
|
446
|
+
planes?: string[];
|
|
447
|
+
/** Dimensions to render. Default: both. */
|
|
448
|
+
dimensions?: Array<'security' | 'perf'>;
|
|
449
|
+
/** GitHub Actions output (job summary, annotations, PR comment). */
|
|
450
|
+
github?: GithubReportConfig;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* What the GitHub integration emits. Defaults render both headline scores,
|
|
454
|
+
* the delta against the compared run, and annotations for gate failures only.
|
|
455
|
+
*/
|
|
456
|
+
export interface GithubReportConfig {
|
|
457
|
+
/**
|
|
458
|
+
* Scores in the job summary, in order. `security`, `perf`, and
|
|
459
|
+
* `planes:<glob>` for secondary planes (e.g. `planes:direct:*`).
|
|
460
|
+
* Default `['security', 'perf']`.
|
|
461
|
+
*/
|
|
462
|
+
summary?: string[];
|
|
463
|
+
/** Sticky PR comment. */
|
|
464
|
+
comment?: GithubCommentConfig;
|
|
465
|
+
/** Which findings become workflow annotations. Default `gate-failures`. */
|
|
466
|
+
annotations?: 'all' | 'gate-failures' | 'none';
|
|
467
|
+
/**
|
|
468
|
+
* How much of the report goes in the job summary. Default `normal`. Set
|
|
469
|
+
* `summary` on a database with thousands of findings: GitHub truncates a job
|
|
470
|
+
* summary at 1 MB, and a truncated report is worse than a short one.
|
|
471
|
+
*/
|
|
472
|
+
detail?: 'summary' | 'normal' | 'verbose';
|
|
473
|
+
/**
|
|
474
|
+
* Render scores as colored shields.io badges. Default `true`; `false` falls
|
|
475
|
+
* back to 🟢/🟡/🔴 text, which needs no network fetch.
|
|
476
|
+
*/
|
|
477
|
+
badges?: boolean;
|
|
478
|
+
}
|
|
479
|
+
export interface GithubCommentConfig {
|
|
480
|
+
/** Reuse one comment per PR instead of appending. Default `true`. */
|
|
481
|
+
sticky?: boolean;
|
|
482
|
+
/**
|
|
483
|
+
* Sections to include, in this order: `scores` (badges + exposure), `planes`,
|
|
484
|
+
* `delta`, `new-findings` (the perf ratchet verdict and what it caught), and
|
|
485
|
+
* `report` — the same markdown report the job summary carries, at `detail`.
|
|
486
|
+
* `findings` is the old name for `report`. Default
|
|
487
|
+
* `['scores', 'delta', 'new-findings']`; add `report` to review the audit
|
|
488
|
+
* without leaving the PR.
|
|
489
|
+
*/
|
|
490
|
+
sections?: Array<'scores' | 'delta' | 'new-findings' | 'report' | 'findings' | 'planes'>;
|
|
491
|
+
/**
|
|
492
|
+
* How much of the report the `report` section carries. Default `summary` —
|
|
493
|
+
* scores, exposure, counts, the delta and the ratchet verdict, with no
|
|
494
|
+
* per-finding tables, because a comment is read on the way past and GitHub
|
|
495
|
+
* rejects a body over 64 KB. `normal`/`verbose` add the finding tables and
|
|
496
|
+
* degrade back to `summary` when the body would not fit.
|
|
497
|
+
*/
|
|
498
|
+
detail?: 'summary' | 'normal' | 'verbose';
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* The full safegres configuration, loadable from `safegres.config.{ts,js,mjs,cjs}`,
|
|
502
|
+
* `.safegresrc{,.json,.yaml,.yml,.js}`, `safegres.json`, or the `"safegres"`
|
|
503
|
+
* key in package.json.
|
|
504
|
+
*/
|
|
505
|
+
export interface SafegresConfig {
|
|
506
|
+
/**
|
|
507
|
+
* Presets (`safegres:recommended`, …), relative paths (`./safegres.base.json`),
|
|
508
|
+
* or npm packages — recursively, lowest precedence first.
|
|
509
|
+
*
|
|
510
|
+
* A path is resolved against the file that declared it, and so is every
|
|
511
|
+
* *path-valued* key inherited from it (`source.pgpm`, `perf.baseline`,
|
|
512
|
+
* `outputs.*`, `eval.corpus`): a baseline written in a shared base file means
|
|
513
|
+
* that file's directory, whichever job inherited it. Objects merge per key
|
|
514
|
+
* and arrays replace, except `overrides`, which is a list of scoped
|
|
515
|
+
* exceptions and so unions across the chain.
|
|
516
|
+
*/
|
|
517
|
+
extends?: string | string[];
|
|
518
|
+
/** The exposed API surface — what the score is computed against. */
|
|
519
|
+
exposure?: ExposureConfig;
|
|
520
|
+
/** Tables whose open reads are deliberate (declared public surface). */
|
|
521
|
+
public?: PublicConfig;
|
|
522
|
+
/** How to treat objects belonging to installed extensions. */
|
|
523
|
+
extensions?: ExtensionsConfig;
|
|
524
|
+
/** The optional performance dimension. */
|
|
525
|
+
perf?: PerfConfig;
|
|
526
|
+
schemas?: string[];
|
|
527
|
+
excludeSchemas?: string[];
|
|
528
|
+
roles?: string[];
|
|
529
|
+
excludeRoles?: string[];
|
|
530
|
+
rules?: RulesConfig;
|
|
531
|
+
overrides?: OverrideEntry[];
|
|
532
|
+
scoring?: ScoringConfig;
|
|
533
|
+
/**
|
|
534
|
+
* Named scores over slices of the same findings — see `ScorecardConfig`.
|
|
535
|
+
* Merged with the reserved `default` and `raw` cards, which always run.
|
|
536
|
+
*/
|
|
537
|
+
scorecards?: Record<string, ScorecardConfig>;
|
|
538
|
+
failOn?: FailOnConfig;
|
|
539
|
+
/** Where the database to audit comes from, when it isn't a live connection. */
|
|
540
|
+
source?: SourceConfig;
|
|
541
|
+
/** Files a single run writes, so CI doesn't have to spell them as flags. */
|
|
542
|
+
outputs?: OutputsConfig;
|
|
543
|
+
/** The unscored call-graph audit (`--call-graph`) and its baseline. */
|
|
544
|
+
callGraph?: CallGraphConfig;
|
|
545
|
+
/** What a rendered report shows — selection, not analysis. */
|
|
546
|
+
report?: ReportConfig;
|
|
547
|
+
/** Defaults for `safegres eval` — which corpus, graded by which preset. */
|
|
548
|
+
eval?: EvalConfig;
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* `safegres eval` defaults. Deliberately only says *what* to run: a case is
|
|
552
|
+
* graded by a named preset, never by the rest of this file, so a project can
|
|
553
|
+
* point eval at its own corpus without also being able to move the answers.
|
|
554
|
+
*/
|
|
555
|
+
export interface EvalConfig {
|
|
556
|
+
/** Corpus directory of `<id>/{case.json,schema.sql}`. Defaults to the shipped one. */
|
|
557
|
+
corpus?: string;
|
|
558
|
+
/** Preset every case is graded under. Defaults to `recommended`. */
|
|
559
|
+
preset?: string;
|
|
560
|
+
/** Case ids (or id prefixes) to run. Defaults to all of them. */
|
|
561
|
+
cases?: string[];
|
|
562
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check a config against the described shape: unknown keys, and values of the
|
|
3
|
+
* wrong kind.
|
|
4
|
+
*
|
|
5
|
+
* A typo'd key used to be *silently ignored*, which for a file that decides
|
|
6
|
+
* whether CI fails is the worst possible outcome — `failon: { grade: 'B' }`
|
|
7
|
+
* reads as a passing build rather than as a mistake. So this rejects rather
|
|
8
|
+
* than warns, and names the key it thinks you meant.
|
|
9
|
+
*
|
|
10
|
+
* Value checks stay shallow on purpose: rule settings, severities and grades
|
|
11
|
+
* are validated by `resolveRules` and by the gate code, which know the rule
|
|
12
|
+
* registry. This is the shape, not the semantics.
|
|
13
|
+
*/
|
|
14
|
+
export declare function validateConfigShape(config: unknown): void;
|