sqlguard-ninja 0.1.0__tar.gz → 0.2.0__tar.gz
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.
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/CHANGELOG.md +44 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/PKG-INFO +46 -41
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/README.md +45 -40
- {sqlguard_ninja-0.1.0/benchmarks/results/v1.0.0 → sqlguard_ninja-0.2.0/benchmarks/baselines}/native.json +4844 -1315
- sqlguard_ninja-0.2.0/benchmarks/datasets/external/README.md +28 -0
- sqlguard_ninja-0.2.0/benchmarks/datasets/v1/LABEL_CHANGES.yaml +22 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/cases/04_privacy.yaml +5 -4
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/cases/05_tenant_isolation.yaml +5 -2
- sqlguard_ninja-0.2.0/benchmarks/datasets/v1/cases/08_lineage.yaml +150 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/manifest.yaml +1 -1
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/agent-sql-guard.csv +1045 -0
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/agent-sql-guard.json +20184 -0
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/agent-sql-guard.md +110 -0
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/krish2105-sqlguard.csv +1045 -0
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/krish2105-sqlguard.json +20121 -0
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/krish2105-sqlguard.md +110 -0
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/native.csv +1045 -0
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/native.json +20484 -0
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/native.md +78 -0
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/sql-guardrail.csv +1045 -0
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/sql-guardrail.json +20779 -0
- sqlguard_ninja-0.2.0/benchmarks/results/v1.1.0/sql-guardrail.md +103 -0
- sqlguard_ninja-0.2.0/docs/benchmarks/RESULTS_v1.1.md +48 -0
- sqlguard_ninja-0.2.0/docs/development/ARCHITECTURE_MAP.md +47 -0
- sqlguard_ninja-0.2.0/docs/development/DECISION_LOG.md +9 -0
- sqlguard_ninja-0.2.0/docs/development/IMPLEMENTATION_PROGRESS.md +7 -0
- sqlguard_ninja-0.2.0/docs/development/NEXT_ACTIONS.md +5 -0
- sqlguard_ninja-0.2.0/docs/development/TEST_EVIDENCE.md +7 -0
- sqlguard_ninja-0.2.0/docs/development/UPGRADE_MASTER_PLAN.md +25 -0
- sqlguard_ninja-0.2.0/docs/development/progress.json +106 -0
- sqlguard_ninja-0.2.0/docs/guides/BENCHMARK_BIAS_REVIEW.md +74 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/docs/guides/BENCHMARK_METHODOLOGY.md +9 -4
- sqlguard_ninja-0.2.0/docs/releases/v0.1.1.md +29 -0
- sqlguard_ninja-0.2.0/docs/releases/v0.2.0.md +27 -0
- sqlguard_ninja-0.2.0/docs/security/STATIC_ANALYSIS_LIMITS.md +49 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/docs/security/THREAT_MODEL.md +4 -0
- sqlguard_ninja-0.2.0/src/sqlguard_ninja/_version.py +1 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/compare.py +8 -1
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/dataset.py +38 -2
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/metrics.py +66 -2
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/runner.py +35 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/cli/config.py +2 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/cli/main.py +34 -5
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/analysis.py +9 -1
- sqlguard_ninja-0.2.0/src/sqlguard_ninja/core/lineage.py +199 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/rules/tenant.py +56 -25
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/privacy/rules.py +53 -14
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/reporting/markdown.py +36 -5
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/unit/test_benchmark_engine.py +77 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/unit/test_cli.py +47 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/unit/test_docs.py +13 -0
- sqlguard_ninja-0.2.0/tests/unit/test_lineage.py +84 -0
- sqlguard_ninja-0.1.0/src/sqlguard_ninja/_version.py +0 -1
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/.gitignore +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/LICENSE +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/THIRD_PARTY_NOTICES.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/cases/01_destructive.yaml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/cases/02_multi_statement_and_formatting.yaml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/cases/03_table_and_column_access.yaml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/cases/06_cte_nested_unicode.yaml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/cases/07_legitimate_lookalike_cost_dialect.yaml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/generated/grant_matrix.yaml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/generated/label_matrix.yaml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/generated/tenant_matrix.yaml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/datasets/v1/generated/transforms.yaml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/policies/retail_saas.yaml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/results/v1.0.0/agent-sql-guard.json +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/results/v1.0.0/agent-sql-guard.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/results/v1.0.0/krish2105-sqlguard.json +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/results/v1.0.0/krish2105-sqlguard.md +0 -0
- {sqlguard_ninja-0.1.0/benchmarks/baselines → sqlguard_ninja-0.2.0/benchmarks/results/v1.0.0}/native.json +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/results/v1.0.0/native.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/results/v1.0.0/sql-guardrail.json +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/benchmarks/results/v1.0.0/sql-guardrail.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/docs/architecture/ARCHITECTURE_DECISIONS.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/docs/benchmarks/RESULTS_v1.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/docs/guides/AGENT_INTEGRATION.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/docs/guides/CI_INTEGRATION.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/docs/guides/POLICY_REFERENCE.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/docs/guides/QUERY_COST.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/docs/release/FINAL_TECHNICAL_AUDIT.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/docs/releases/v0.1.0.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/docs/research/COMPETITIVE_ANALYSIS.md +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/examples/_shared.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/examples/fastapi/app.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/examples/github-actions/sql-security.yml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/examples/langchain/guarded_tool_demo.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/examples/langgraph/real_llm_agent.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/examples/langgraph/sql_agent_demo.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/examples/postgresql/plan_inspection_demo.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/examples/sdk/quickstart.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/examples/sqlite/text_to_sql_demo.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/pyproject.toml +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/adapters.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/builtin.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/fixtures.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/translate.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/workers/_protocol.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/workers/agent_sql_guard_worker.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/workers/krish_sqlguard_worker.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/benchmarking/workers/sql_guardrail_worker.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/cli/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/cli/templates.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/findings.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/guard.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/rules/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/rules/access.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/rules/base.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/rules/catalog.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/rules/functions.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/rules/statements.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/core/rules/structure.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/integrations/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/integrations/audit.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/integrations/checkpoint.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/integrations/executors.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/integrations/fastapi.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/integrations/langchain.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/integrations/langgraph.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/policy/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/policy/model.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/privacy/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/privacy/suggest.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/py.typed +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/query_cost/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/query_cost/postgres.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/query_cost/static.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/src/sqlguard_ninja/reporting/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/conftest.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/integration/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/integration/test_corpus_sqlite_validation.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/integration/test_external_adapters.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/integration/test_frameworks.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/integration/test_postgres.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/pg_support.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/property/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/property/test_guard_properties.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/security/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/security/test_agent_boundaries.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/security/test_corpus_native.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/unit/__init__.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/unit/helpers.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/unit/test_dataset.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/unit/test_function_policy_mechanics.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/unit/test_policy.py +0 -0
- {sqlguard_ninja-0.1.0 → sqlguard_ninja-0.2.0}/tests/unit/test_rules.py +0 -0
|
@@ -3,6 +3,50 @@
|
|
|
3
3
|
All notable changes are documented here. The project follows
|
|
4
4
|
[Semantic Versioning](https://semver.org/); before 1.0, minor versions may change the API.
|
|
5
5
|
|
|
6
|
+
## [0.2.0] — 2026-10-24
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
* **Lineage-aware privacy** (`core/lineage.py`). An `aggregate_only` column projected raw in a
|
|
10
|
+
CTE or derived table is accepted only when every downstream consumer aggregates it
|
|
11
|
+
statistically. Whole-row use, filters, ordering, windows, MIN/MAX and a raw use by any
|
|
12
|
+
consumer stay denied (issue #8).
|
|
13
|
+
* **Tenant push-down.** An outer tenant pin on an unmodified projection of the tenant column
|
|
14
|
+
satisfies the inner read when the inner scope has no aggregation, window, LIMIT, OFFSET or
|
|
15
|
+
FETCH and every consumer pins it, recursively (issue #9).
|
|
16
|
+
* The small-cohort check follows identifiers through CTEs and derived tables, so the lineage
|
|
17
|
+
relaxation cannot bypass it (found by new boundary case LIN-012).
|
|
18
|
+
* Privacy findings carry structured lineage metadata (base column, JSON path, scope, labels).
|
|
19
|
+
* Benchmark: `internal` / `independent` dataset tiers, flag basis (policy vs unsupported SQL),
|
|
20
|
+
F1, 95% Wilson intervals, throughput, CSV output (`--csv`), per-file SHA-256 dataset hashes
|
|
21
|
+
in results and `sqlninja dataset stats`.
|
|
22
|
+
* Approved-relabel workflow: `LABEL_CHANGES.yaml` (CODEOWNERS-protected) lists reviewed label
|
|
23
|
+
changes; `benchmark compare --approved-label-changes` / `ci.approved_label_changes`.
|
|
24
|
+
* Corpus 1.1.0: 21 lineage boundary cases; 2 approved relabels (PRV-026, TEN-021).
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
* Decisions changed for exactly two corpus cases (PRV-026, TEN-021: deny → allow); all other
|
|
28
|
+
1,042 evaluations are unchanged.
|
|
29
|
+
|
|
30
|
+
## [0.1.1] — 2026-10-24
|
|
31
|
+
|
|
32
|
+
Documentation and governance patch. No changes to policy decisions.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
* README links were relative and broke on the PyPI project page. They are now absolute
|
|
36
|
+
GitHub URLs, and a test keeps relative links out of the README.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
* `docs/security/STATIC_ANALYSIS_LIMITS.md`: limits of static analysis, compensating
|
|
40
|
+
controls, and a dialect support matrix (supported / experimental / untested).
|
|
41
|
+
* `docs/guides/BENCHMARK_BIAS_REVIEW.md`: quantified review of corpus v1 bias
|
|
42
|
+
(co-development, generated labels, input distribution, outcome imbalance).
|
|
43
|
+
* `benchmarks/datasets/external/`: intake rules for independently sourced, held-out
|
|
44
|
+
evaluation sets (no cases yet).
|
|
45
|
+
* `.github/CODEOWNERS`, and branch protection on `main` (pull requests and CI required).
|
|
46
|
+
|
|
47
|
+
### Unchanged known limitations
|
|
48
|
+
* No restricted-function or system-catalog benchmark cases; no external dataset yet.
|
|
49
|
+
|
|
6
50
|
## [0.1.0] — 2026-10-24
|
|
7
51
|
|
|
8
52
|
First release.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sqlguard-ninja
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Security testing, policy enforcement, agent integration, privacy analysis and CI benchmarking for LLM-generated SQL.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Pratik653/SQLGuard_Ninjapy
|
|
6
6
|
Project-URL: Documentation, https://github.com/Pratik653/SQLGuard_Ninjapy/tree/main/docs
|
|
@@ -70,29 +70,29 @@ the *authenticated* caller: which tables and columns a role may use, which data
|
|
|
70
70
|
appear only in aggregates or only after human approval, and which tenant the caller belongs
|
|
71
71
|
to. It records an audit trail and gives the agent an explanation it can act on.
|
|
72
72
|
|
|
73
|
-
It ships with a labelled benchmark corpus (
|
|
73
|
+
It ships with a labelled benchmark corpus (551 cases, 1,044 dialect evaluations) and a
|
|
74
74
|
regression gate for CI. The same benchmark harness can evaluate other open-source guards
|
|
75
75
|
side by side.
|
|
76
76
|
|
|
77
77
|
> **One layer, not the only one.** Static SQL inspection cannot guarantee database security.
|
|
78
78
|
> Use a read-only least-privilege role, row-level security and statement timeouts as well.
|
|
79
|
-
> See the [threat model](docs/security/THREAT_MODEL.md).
|
|
79
|
+
> See the [threat model](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/security/THREAT_MODEL.md).
|
|
80
80
|
|
|
81
81
|
## What it does
|
|
82
82
|
|
|
83
83
|
| Workstream | What you get | Status |
|
|
84
84
|
|---|---|---|
|
|
85
85
|
| **Policy engine** | Read-only enforcement, table/column grants, tenant isolation, function and catalog rules, structural limits. Built on [sqlglot](https://github.com/tobymao/sqlglot). Fails closed when analysis is incomplete. | PostgreSQL + SQLite tested |
|
|
86
|
-
| **Privacy pack** | Explicit classification labels, `deny` / `aggregate_only` / `review` per role, JSON-path labels, small-cohort review, minimisation hints and alternatives | implemented |
|
|
86
|
+
| **Privacy pack** | Explicit classification labels, `deny` / `aggregate_only` / `review` per role, JSON-path labels, lineage through CTEs and derived tables, small-cohort review, minimisation hints and alternatives | implemented |
|
|
87
87
|
| **Agent integrations** | `SQLCheckpoint` with block / review / audit modes, hash-bound single-use approvals, retry lock-out, redacted audit events. LangChain tool, LangGraph nodes, FastAPI router | implemented |
|
|
88
|
-
| **Benchmark engine** | Versioned corpus, metrics (recall, precision, FPR, FNR, exact match, per category/dialect
|
|
88
|
+
| **Benchmark engine** | Versioned corpus with per-file SHA-256 hashes, internal and independent tiers, metrics (recall, precision, F1, FPR, FNR with 95% Wilson intervals, exact match, throughput, latency percentiles, per category/dialect/tier), adapters for native, callable and isolated external validators, JSON, CSV and Markdown reports | implemented |
|
|
89
89
|
| **Query cost** | Explainable static score; optional PostgreSQL `EXPLAIN (FORMAT JSON)` inspection, gated and read-only | implemented |
|
|
90
90
|
| **CI** | Composite GitHub Action and CLI gate: security, usability, label-change and error regressions against an approved baseline | implemented |
|
|
91
91
|
|
|
92
92
|
Not yet included: governed writes (all writes are denied in v0.1); benchmark cases for
|
|
93
93
|
restricted functions and system catalogs (the rules exist, but the corpus does not cover
|
|
94
94
|
them); dialects beyond PostgreSQL and SQLite (they parse, but are untested). Full list:
|
|
95
|
-
[KNOWN_LIMITATIONS.md](KNOWN_LIMITATIONS.md).
|
|
95
|
+
[KNOWN_LIMITATIONS.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/KNOWN_LIMITATIONS.md).
|
|
96
96
|
|
|
97
97
|
## Architecture
|
|
98
98
|
|
|
@@ -121,7 +121,7 @@ flowchart LR
|
|
|
121
121
|
```
|
|
122
122
|
|
|
123
123
|
Design decisions and their trade-offs are recorded in
|
|
124
|
-
[ARCHITECTURE_DECISIONS.md](docs/architecture/ARCHITECTURE_DECISIONS.md).
|
|
124
|
+
[ARCHITECTURE_DECISIONS.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/architecture/ARCHITECTURE_DECISIONS.md).
|
|
125
125
|
|
|
126
126
|
## Five-minute quick start
|
|
127
127
|
|
|
@@ -203,7 +203,7 @@ ctx = RequestContext(principal=user.id, role=user.role, tenant_id=user.tenant_id
|
|
|
203
203
|
app.invoke(state, config={"configurable": {CONTEXT_KEY: ctx}}) # nodes cannot alter config
|
|
204
204
|
```
|
|
205
205
|
|
|
206
|
-
More in [AGENT_INTEGRATION.md](docs/guides/AGENT_INTEGRATION.md): the LangChain tool (its
|
|
206
|
+
More in [AGENT_INTEGRATION.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/AGENT_INTEGRATION.md): the LangChain tool (its
|
|
207
207
|
schema accepts only `query`), the FastAPI router, review-mode approvals and audit sinks.
|
|
208
208
|
|
|
209
209
|
## Privacy policies
|
|
@@ -244,7 +244,7 @@ REVIEW:
|
|
|
244
244
|
Labels also apply to paths inside JSON columns (`profile->'health'->>'allergies'`).
|
|
245
245
|
`sqlninja policy suggest` proposes labels from column names for a human to review; those
|
|
246
246
|
suggestions are never enforced. This is a technical control, not a certification of GDPR
|
|
247
|
-
compliance. Full semantics: [POLICY_REFERENCE.md](docs/guides/POLICY_REFERENCE.md).
|
|
247
|
+
compliance. Full semantics: [POLICY_REFERENCE.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_REFERENCE.md).
|
|
248
248
|
|
|
249
249
|
## Query cost analysis
|
|
250
250
|
|
|
@@ -268,7 +268,7 @@ report = PostgresPlanInspector(guard, lambda: psycopg.connect(READER_DSN)).inspe
|
|
|
268
268
|
report.total_cost, report.plan_rows, report.static.score, report.findings
|
|
269
269
|
```
|
|
270
270
|
|
|
271
|
-
See [QUERY_COST.md](docs/guides/QUERY_COST.md) and `examples/postgresql/plan_inspection_demo.py`.
|
|
271
|
+
See [QUERY_COST.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/QUERY_COST.md) and `examples/postgresql/plan_inspection_demo.py`.
|
|
272
272
|
|
|
273
273
|
## Benchmark
|
|
274
274
|
|
|
@@ -279,22 +279,24 @@ sqlninja benchmark run --dataset builtin:v1 --adapter external:sql-guardrail
|
|
|
279
279
|
sqlninja benchmark compare --baseline benchmarks/baselines/native.json --candidate results/latest.json
|
|
280
280
|
```
|
|
281
281
|
|
|
282
|
-
Results for corpus v1.
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
|
289
|
-
|
|
|
290
|
-
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
100% shows consistency with the documented semantics, not independent
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
282
|
+
Results for corpus v1.1.0 (551 cases, 1,044 evaluations; SQLGuard Ninja 0.2.0; Windows 11,
|
|
283
|
+
Python 3.11). Intervals are 95% Wilson intervals. Details, CSV and raw files:
|
|
284
|
+
[RESULTS_v1.1.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/benchmarks/RESULTS_v1.1.md).
|
|
285
|
+
|
|
286
|
+
| Validator | Recall (95% CI) | Precision | F1 | FPR (95% CI) | Recall / FPR within declared capability | p95 ms |
|
|
287
|
+
|---|---:|---:|---:|---:|---:|---:|
|
|
288
|
+
| SQLGuard Ninja 0.2.0 | 100.0% (99.4–100.0) | 100.0% | 1.000 | 0.0% (0.0–0.9) | 100.0% / 0.0% | 3.33 |
|
|
289
|
+
| sql-guardrail 0.5.2 | 98.7% (97.4–99.3) | 85.1% | 0.914 | 24.1% (20.3–28.3) | 98.3% / 19.7% | 2.63 |
|
|
290
|
+
| agent-sql-guard 0.2.0 | 67.3% (63.4–70.9) | 85.2% | 0.752 | 16.3% (13.1–20.0) | 89.4% / 17.7% | 1.87 |
|
|
291
|
+
| krish2105/sqlguard 0.1.0 | 65.3% (61.4–69.0) | 89.6% | 0.755 | 10.5% (8.0–13.8) | 83.5% / 5.2% | 1.95 |
|
|
292
|
+
|
|
293
|
+
**All of these are internal results.** The corpus was written by this project, alongside the
|
|
294
|
+
engine. The native 100% shows consistency with the documented semantics, not independent
|
|
295
|
+
detection quality. No independently sourced dataset exists yet ([intake rules](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/benchmarks/datasets/external/README.md),
|
|
296
|
+
issue #6). Reports keep `internal` and `independent` tiers separate, and they also separate
|
|
297
|
+
policy denials from unsupported-SQL denials. Methodology and bias review:
|
|
298
|
+
[BENCHMARK_METHODOLOGY.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_METHODOLOGY.md),
|
|
299
|
+
[BENCHMARK_BIAS_REVIEW.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_BIAS_REVIEW.md).
|
|
298
300
|
|
|
299
301
|
## How it relates to existing tools
|
|
300
302
|
|
|
@@ -304,7 +306,7 @@ thorough read-only validator with a tautology catch-all, which this project does
|
|
|
304
306
|
duplicate. [agent-sql-guard](https://github.com/sakura-sky/sql-guard) has a careful
|
|
305
307
|
schema-less PII denylist. What SQLGuard Ninja adds: role- and label-based policies, the agent
|
|
306
308
|
checkpoint contract, a shared benchmark with isolated adapters, planner inspection, and the
|
|
307
|
-
CI gate. Full comparison: [COMPETITIVE_ANALYSIS.md](docs/research/COMPETITIVE_ANALYSIS.md).
|
|
309
|
+
CI gate. Full comparison: [COMPETITIVE_ANALYSIS.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/research/COMPETITIVE_ANALYSIS.md).
|
|
308
310
|
|
|
309
311
|
## Security limitations
|
|
310
312
|
|
|
@@ -318,13 +320,14 @@ CI gate. Full comparison: [COMPETITIVE_ANALYSIS.md](docs/research/COMPETITIVE_AN
|
|
|
318
320
|
but those two categories are not measured.
|
|
319
321
|
|
|
320
322
|
Use database grants, row-level security and timeouts as the authoritative controls. See the
|
|
321
|
-
[threat model](docs/security/THREAT_MODEL.md)
|
|
323
|
+
[threat model](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/security/THREAT_MODEL.md), [limits of static analysis](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/security/STATIC_ANALYSIS_LIMITS.md),
|
|
324
|
+
the [benchmark bias review](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_BIAS_REVIEW.md) and [KNOWN_LIMITATIONS.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/KNOWN_LIMITATIONS.md).
|
|
322
325
|
|
|
323
326
|
## Roadmap
|
|
324
327
|
|
|
325
328
|
Next: restricted-function and system-catalog benchmark cases, an independent held-out
|
|
326
329
|
corpus, lineage-aware aggregate checks, and tenant predicate push-down. Later: governed
|
|
327
|
-
writes, more tested dialects, and SARIF output. Details in [ROADMAP.md](ROADMAP.md).
|
|
330
|
+
writes, more tested dialects, and SARIF output. Details in [ROADMAP.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/ROADMAP.md).
|
|
328
331
|
|
|
329
332
|
## Links
|
|
330
333
|
|
|
@@ -332,18 +335,20 @@ writes, more tested dialects, and SARIF output. Details in [ROADMAP.md](ROADMAP.
|
|
|
332
335
|
* Releases: https://github.com/Pratik653/SQLGuard_Ninjapy/releases
|
|
333
336
|
* PyPI: https://pypi.org/project/sqlguard-ninja/
|
|
334
337
|
* Issues: https://github.com/Pratik653/SQLGuard_Ninjapy/issues
|
|
335
|
-
* Security policy: [SECURITY.md](SECURITY.md) · Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
338
|
+
* Security policy: [SECURITY.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/SECURITY.md) · Contributing: [CONTRIBUTING.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/CONTRIBUTING.md)
|
|
336
339
|
|
|
337
340
|
## Documentation
|
|
338
341
|
|
|
339
|
-
* [Policy reference](docs/guides/POLICY_REFERENCE.md)
|
|
340
|
-
* [Agent integration](docs/guides/AGENT_INTEGRATION.md)
|
|
341
|
-
* [Query cost](docs/guides/QUERY_COST.md)
|
|
342
|
-
* [CI integration](docs/guides/CI_INTEGRATION.md)
|
|
343
|
-
* [Benchmark methodology](docs/guides/BENCHMARK_METHODOLOGY.md)
|
|
344
|
-
* [Threat model](docs/security/THREAT_MODEL.md)
|
|
345
|
-
* [
|
|
346
|
-
* [
|
|
342
|
+
* [Policy reference](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_REFERENCE.md)
|
|
343
|
+
* [Agent integration](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/AGENT_INTEGRATION.md)
|
|
344
|
+
* [Query cost](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/QUERY_COST.md)
|
|
345
|
+
* [CI integration](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/CI_INTEGRATION.md)
|
|
346
|
+
* [Benchmark methodology](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_METHODOLOGY.md)
|
|
347
|
+
* [Threat model](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/security/THREAT_MODEL.md)
|
|
348
|
+
* [Limits of static SQL analysis and dialect support](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/security/STATIC_ANALYSIS_LIMITS.md)
|
|
349
|
+
* [Benchmark bias review](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_BIAS_REVIEW.md)
|
|
350
|
+
* [Architecture decisions](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/architecture/ARCHITECTURE_DECISIONS.md)
|
|
351
|
+
* [Known limitations](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/KNOWN_LIMITATIONS.md) · [Roadmap](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/ROADMAP.md) · [Changelog](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/CHANGELOG.md)
|
|
347
352
|
|
|
348
353
|
## Supported versions
|
|
349
354
|
|
|
@@ -361,10 +366,10 @@ pytest # PostgreSQL tests run if SQLNINJA_PG_DSN is set
|
|
|
361
366
|
python scripts/generate_corpus.py --check
|
|
362
367
|
```
|
|
363
368
|
|
|
364
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md). Report vulnerabilities privately per
|
|
365
|
-
[SECURITY.md](SECURITY.md).
|
|
369
|
+
See [CONTRIBUTING.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/CONTRIBUTING.md). Report vulnerabilities privately per
|
|
370
|
+
[SECURITY.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/SECURITY.md).
|
|
366
371
|
|
|
367
372
|
## Licence
|
|
368
373
|
|
|
369
374
|
Apache-2.0. No third-party code is vendored; dependencies and their licences are listed in
|
|
370
|
-
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md). All benchmark data is synthetic.
|
|
375
|
+
[THIRD_PARTY_NOTICES.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/THIRD_PARTY_NOTICES.md). All benchmark data is synthetic.
|
|
@@ -14,29 +14,29 @@ the *authenticated* caller: which tables and columns a role may use, which data
|
|
|
14
14
|
appear only in aggregates or only after human approval, and which tenant the caller belongs
|
|
15
15
|
to. It records an audit trail and gives the agent an explanation it can act on.
|
|
16
16
|
|
|
17
|
-
It ships with a labelled benchmark corpus (
|
|
17
|
+
It ships with a labelled benchmark corpus (551 cases, 1,044 dialect evaluations) and a
|
|
18
18
|
regression gate for CI. The same benchmark harness can evaluate other open-source guards
|
|
19
19
|
side by side.
|
|
20
20
|
|
|
21
21
|
> **One layer, not the only one.** Static SQL inspection cannot guarantee database security.
|
|
22
22
|
> Use a read-only least-privilege role, row-level security and statement timeouts as well.
|
|
23
|
-
> See the [threat model](docs/security/THREAT_MODEL.md).
|
|
23
|
+
> See the [threat model](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/security/THREAT_MODEL.md).
|
|
24
24
|
|
|
25
25
|
## What it does
|
|
26
26
|
|
|
27
27
|
| Workstream | What you get | Status |
|
|
28
28
|
|---|---|---|
|
|
29
29
|
| **Policy engine** | Read-only enforcement, table/column grants, tenant isolation, function and catalog rules, structural limits. Built on [sqlglot](https://github.com/tobymao/sqlglot). Fails closed when analysis is incomplete. | PostgreSQL + SQLite tested |
|
|
30
|
-
| **Privacy pack** | Explicit classification labels, `deny` / `aggregate_only` / `review` per role, JSON-path labels, small-cohort review, minimisation hints and alternatives | implemented |
|
|
30
|
+
| **Privacy pack** | Explicit classification labels, `deny` / `aggregate_only` / `review` per role, JSON-path labels, lineage through CTEs and derived tables, small-cohort review, minimisation hints and alternatives | implemented |
|
|
31
31
|
| **Agent integrations** | `SQLCheckpoint` with block / review / audit modes, hash-bound single-use approvals, retry lock-out, redacted audit events. LangChain tool, LangGraph nodes, FastAPI router | implemented |
|
|
32
|
-
| **Benchmark engine** | Versioned corpus, metrics (recall, precision, FPR, FNR, exact match, per category/dialect
|
|
32
|
+
| **Benchmark engine** | Versioned corpus with per-file SHA-256 hashes, internal and independent tiers, metrics (recall, precision, F1, FPR, FNR with 95% Wilson intervals, exact match, throughput, latency percentiles, per category/dialect/tier), adapters for native, callable and isolated external validators, JSON, CSV and Markdown reports | implemented |
|
|
33
33
|
| **Query cost** | Explainable static score; optional PostgreSQL `EXPLAIN (FORMAT JSON)` inspection, gated and read-only | implemented |
|
|
34
34
|
| **CI** | Composite GitHub Action and CLI gate: security, usability, label-change and error regressions against an approved baseline | implemented |
|
|
35
35
|
|
|
36
36
|
Not yet included: governed writes (all writes are denied in v0.1); benchmark cases for
|
|
37
37
|
restricted functions and system catalogs (the rules exist, but the corpus does not cover
|
|
38
38
|
them); dialects beyond PostgreSQL and SQLite (they parse, but are untested). Full list:
|
|
39
|
-
[KNOWN_LIMITATIONS.md](KNOWN_LIMITATIONS.md).
|
|
39
|
+
[KNOWN_LIMITATIONS.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/KNOWN_LIMITATIONS.md).
|
|
40
40
|
|
|
41
41
|
## Architecture
|
|
42
42
|
|
|
@@ -65,7 +65,7 @@ flowchart LR
|
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
Design decisions and their trade-offs are recorded in
|
|
68
|
-
[ARCHITECTURE_DECISIONS.md](docs/architecture/ARCHITECTURE_DECISIONS.md).
|
|
68
|
+
[ARCHITECTURE_DECISIONS.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/architecture/ARCHITECTURE_DECISIONS.md).
|
|
69
69
|
|
|
70
70
|
## Five-minute quick start
|
|
71
71
|
|
|
@@ -147,7 +147,7 @@ ctx = RequestContext(principal=user.id, role=user.role, tenant_id=user.tenant_id
|
|
|
147
147
|
app.invoke(state, config={"configurable": {CONTEXT_KEY: ctx}}) # nodes cannot alter config
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
More in [AGENT_INTEGRATION.md](docs/guides/AGENT_INTEGRATION.md): the LangChain tool (its
|
|
150
|
+
More in [AGENT_INTEGRATION.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/AGENT_INTEGRATION.md): the LangChain tool (its
|
|
151
151
|
schema accepts only `query`), the FastAPI router, review-mode approvals and audit sinks.
|
|
152
152
|
|
|
153
153
|
## Privacy policies
|
|
@@ -188,7 +188,7 @@ REVIEW:
|
|
|
188
188
|
Labels also apply to paths inside JSON columns (`profile->'health'->>'allergies'`).
|
|
189
189
|
`sqlninja policy suggest` proposes labels from column names for a human to review; those
|
|
190
190
|
suggestions are never enforced. This is a technical control, not a certification of GDPR
|
|
191
|
-
compliance. Full semantics: [POLICY_REFERENCE.md](docs/guides/POLICY_REFERENCE.md).
|
|
191
|
+
compliance. Full semantics: [POLICY_REFERENCE.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_REFERENCE.md).
|
|
192
192
|
|
|
193
193
|
## Query cost analysis
|
|
194
194
|
|
|
@@ -212,7 +212,7 @@ report = PostgresPlanInspector(guard, lambda: psycopg.connect(READER_DSN)).inspe
|
|
|
212
212
|
report.total_cost, report.plan_rows, report.static.score, report.findings
|
|
213
213
|
```
|
|
214
214
|
|
|
215
|
-
See [QUERY_COST.md](docs/guides/QUERY_COST.md) and `examples/postgresql/plan_inspection_demo.py`.
|
|
215
|
+
See [QUERY_COST.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/QUERY_COST.md) and `examples/postgresql/plan_inspection_demo.py`.
|
|
216
216
|
|
|
217
217
|
## Benchmark
|
|
218
218
|
|
|
@@ -223,22 +223,24 @@ sqlninja benchmark run --dataset builtin:v1 --adapter external:sql-guardrail
|
|
|
223
223
|
sqlninja benchmark compare --baseline benchmarks/baselines/native.json --candidate results/latest.json
|
|
224
224
|
```
|
|
225
225
|
|
|
226
|
-
Results for corpus v1.
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
|
233
|
-
|
|
|
234
|
-
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
100% shows consistency with the documented semantics, not independent
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
226
|
+
Results for corpus v1.1.0 (551 cases, 1,044 evaluations; SQLGuard Ninja 0.2.0; Windows 11,
|
|
227
|
+
Python 3.11). Intervals are 95% Wilson intervals. Details, CSV and raw files:
|
|
228
|
+
[RESULTS_v1.1.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/benchmarks/RESULTS_v1.1.md).
|
|
229
|
+
|
|
230
|
+
| Validator | Recall (95% CI) | Precision | F1 | FPR (95% CI) | Recall / FPR within declared capability | p95 ms |
|
|
231
|
+
|---|---:|---:|---:|---:|---:|---:|
|
|
232
|
+
| SQLGuard Ninja 0.2.0 | 100.0% (99.4–100.0) | 100.0% | 1.000 | 0.0% (0.0–0.9) | 100.0% / 0.0% | 3.33 |
|
|
233
|
+
| sql-guardrail 0.5.2 | 98.7% (97.4–99.3) | 85.1% | 0.914 | 24.1% (20.3–28.3) | 98.3% / 19.7% | 2.63 |
|
|
234
|
+
| agent-sql-guard 0.2.0 | 67.3% (63.4–70.9) | 85.2% | 0.752 | 16.3% (13.1–20.0) | 89.4% / 17.7% | 1.87 |
|
|
235
|
+
| krish2105/sqlguard 0.1.0 | 65.3% (61.4–69.0) | 89.6% | 0.755 | 10.5% (8.0–13.8) | 83.5% / 5.2% | 1.95 |
|
|
236
|
+
|
|
237
|
+
**All of these are internal results.** The corpus was written by this project, alongside the
|
|
238
|
+
engine. The native 100% shows consistency with the documented semantics, not independent
|
|
239
|
+
detection quality. No independently sourced dataset exists yet ([intake rules](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/benchmarks/datasets/external/README.md),
|
|
240
|
+
issue #6). Reports keep `internal` and `independent` tiers separate, and they also separate
|
|
241
|
+
policy denials from unsupported-SQL denials. Methodology and bias review:
|
|
242
|
+
[BENCHMARK_METHODOLOGY.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_METHODOLOGY.md),
|
|
243
|
+
[BENCHMARK_BIAS_REVIEW.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_BIAS_REVIEW.md).
|
|
242
244
|
|
|
243
245
|
## How it relates to existing tools
|
|
244
246
|
|
|
@@ -248,7 +250,7 @@ thorough read-only validator with a tautology catch-all, which this project does
|
|
|
248
250
|
duplicate. [agent-sql-guard](https://github.com/sakura-sky/sql-guard) has a careful
|
|
249
251
|
schema-less PII denylist. What SQLGuard Ninja adds: role- and label-based policies, the agent
|
|
250
252
|
checkpoint contract, a shared benchmark with isolated adapters, planner inspection, and the
|
|
251
|
-
CI gate. Full comparison: [COMPETITIVE_ANALYSIS.md](docs/research/COMPETITIVE_ANALYSIS.md).
|
|
253
|
+
CI gate. Full comparison: [COMPETITIVE_ANALYSIS.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/research/COMPETITIVE_ANALYSIS.md).
|
|
252
254
|
|
|
253
255
|
## Security limitations
|
|
254
256
|
|
|
@@ -262,13 +264,14 @@ CI gate. Full comparison: [COMPETITIVE_ANALYSIS.md](docs/research/COMPETITIVE_AN
|
|
|
262
264
|
but those two categories are not measured.
|
|
263
265
|
|
|
264
266
|
Use database grants, row-level security and timeouts as the authoritative controls. See the
|
|
265
|
-
[threat model](docs/security/THREAT_MODEL.md)
|
|
267
|
+
[threat model](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/security/THREAT_MODEL.md), [limits of static analysis](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/security/STATIC_ANALYSIS_LIMITS.md),
|
|
268
|
+
the [benchmark bias review](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_BIAS_REVIEW.md) and [KNOWN_LIMITATIONS.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/KNOWN_LIMITATIONS.md).
|
|
266
269
|
|
|
267
270
|
## Roadmap
|
|
268
271
|
|
|
269
272
|
Next: restricted-function and system-catalog benchmark cases, an independent held-out
|
|
270
273
|
corpus, lineage-aware aggregate checks, and tenant predicate push-down. Later: governed
|
|
271
|
-
writes, more tested dialects, and SARIF output. Details in [ROADMAP.md](ROADMAP.md).
|
|
274
|
+
writes, more tested dialects, and SARIF output. Details in [ROADMAP.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/ROADMAP.md).
|
|
272
275
|
|
|
273
276
|
## Links
|
|
274
277
|
|
|
@@ -276,18 +279,20 @@ writes, more tested dialects, and SARIF output. Details in [ROADMAP.md](ROADMAP.
|
|
|
276
279
|
* Releases: https://github.com/Pratik653/SQLGuard_Ninjapy/releases
|
|
277
280
|
* PyPI: https://pypi.org/project/sqlguard-ninja/
|
|
278
281
|
* Issues: https://github.com/Pratik653/SQLGuard_Ninjapy/issues
|
|
279
|
-
* Security policy: [SECURITY.md](SECURITY.md) · Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
282
|
+
* Security policy: [SECURITY.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/SECURITY.md) · Contributing: [CONTRIBUTING.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/CONTRIBUTING.md)
|
|
280
283
|
|
|
281
284
|
## Documentation
|
|
282
285
|
|
|
283
|
-
* [Policy reference](docs/guides/POLICY_REFERENCE.md)
|
|
284
|
-
* [Agent integration](docs/guides/AGENT_INTEGRATION.md)
|
|
285
|
-
* [Query cost](docs/guides/QUERY_COST.md)
|
|
286
|
-
* [CI integration](docs/guides/CI_INTEGRATION.md)
|
|
287
|
-
* [Benchmark methodology](docs/guides/BENCHMARK_METHODOLOGY.md)
|
|
288
|
-
* [Threat model](docs/security/THREAT_MODEL.md)
|
|
289
|
-
* [
|
|
290
|
-
* [
|
|
286
|
+
* [Policy reference](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_REFERENCE.md)
|
|
287
|
+
* [Agent integration](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/AGENT_INTEGRATION.md)
|
|
288
|
+
* [Query cost](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/QUERY_COST.md)
|
|
289
|
+
* [CI integration](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/CI_INTEGRATION.md)
|
|
290
|
+
* [Benchmark methodology](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_METHODOLOGY.md)
|
|
291
|
+
* [Threat model](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/security/THREAT_MODEL.md)
|
|
292
|
+
* [Limits of static SQL analysis and dialect support](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/security/STATIC_ANALYSIS_LIMITS.md)
|
|
293
|
+
* [Benchmark bias review](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_BIAS_REVIEW.md)
|
|
294
|
+
* [Architecture decisions](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/architecture/ARCHITECTURE_DECISIONS.md)
|
|
295
|
+
* [Known limitations](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/KNOWN_LIMITATIONS.md) · [Roadmap](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/ROADMAP.md) · [Changelog](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/CHANGELOG.md)
|
|
291
296
|
|
|
292
297
|
## Supported versions
|
|
293
298
|
|
|
@@ -305,10 +310,10 @@ pytest # PostgreSQL tests run if SQLNINJA_PG_DSN is set
|
|
|
305
310
|
python scripts/generate_corpus.py --check
|
|
306
311
|
```
|
|
307
312
|
|
|
308
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md). Report vulnerabilities privately per
|
|
309
|
-
[SECURITY.md](SECURITY.md).
|
|
313
|
+
See [CONTRIBUTING.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/CONTRIBUTING.md). Report vulnerabilities privately per
|
|
314
|
+
[SECURITY.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/SECURITY.md).
|
|
310
315
|
|
|
311
316
|
## Licence
|
|
312
317
|
|
|
313
318
|
Apache-2.0. No third-party code is vendored; dependencies and their licences are listed in
|
|
314
|
-
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md). All benchmark data is synthetic.
|
|
319
|
+
[THIRD_PARTY_NOTICES.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/THIRD_PARTY_NOTICES.md). All benchmark data is synthetic.
|