sqlguard-ninja 0.1.1__tar.gz → 0.3.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.1 → sqlguard_ninja-0.3.0}/CHANGELOG.md +45 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/PKG-INFO +40 -20
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/README.md +39 -19
- {sqlguard_ninja-0.1.1/benchmarks/results/v1.0.0 → sqlguard_ninja-0.3.0/benchmarks/baselines}/native.json +4844 -1315
- sqlguard_ninja-0.3.0/benchmarks/datasets/v1/LABEL_CHANGES.yaml +22 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/cases/04_privacy.yaml +5 -4
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/cases/05_tenant_isolation.yaml +5 -2
- sqlguard_ninja-0.3.0/benchmarks/datasets/v1/cases/08_lineage.yaml +150 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/manifest.yaml +1 -1
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/agent-sql-guard.csv +1045 -0
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/agent-sql-guard.json +20184 -0
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/agent-sql-guard.md +110 -0
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/krish2105-sqlguard.csv +1045 -0
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/krish2105-sqlguard.json +20121 -0
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/krish2105-sqlguard.md +110 -0
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/native.csv +1045 -0
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/native.json +20484 -0
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/native.md +78 -0
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/sql-guardrail.csv +1045 -0
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/sql-guardrail.json +20779 -0
- sqlguard_ninja-0.3.0/benchmarks/results/v1.1.0/sql-guardrail.md +103 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/architecture/ARCHITECTURE_DECISIONS.md +19 -0
- sqlguard_ninja-0.3.0/docs/benchmarks/RESULTS_v1.1.md +48 -0
- sqlguard_ninja-0.3.0/docs/development/ARCHITECTURE_MAP.md +47 -0
- sqlguard_ninja-0.3.0/docs/development/DECISION_LOG.md +9 -0
- sqlguard_ninja-0.3.0/docs/development/IMPLEMENTATION_PROGRESS.md +11 -0
- sqlguard_ninja-0.3.0/docs/development/NEXT_ACTIONS.md +5 -0
- sqlguard_ninja-0.3.0/docs/development/TEST_EVIDENCE.md +12 -0
- sqlguard_ninja-0.3.0/docs/development/UPGRADE_MASTER_PLAN.md +25 -0
- sqlguard_ninja-0.3.0/docs/development/progress.json +110 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/guides/AGENT_INTEGRATION.md +3 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/guides/BENCHMARK_BIAS_REVIEW.md +1 -1
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/guides/BENCHMARK_METHODOLOGY.md +7 -4
- sqlguard_ninja-0.3.0/docs/guides/POLICY_AS_CODE.md +97 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/guides/POLICY_REFERENCE.md +5 -0
- sqlguard_ninja-0.3.0/docs/releases/v0.2.0.md +27 -0
- sqlguard_ninja-0.3.0/docs/releases/v0.3.0.md +29 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/security/THREAT_MODEL.md +2 -0
- sqlguard_ninja-0.3.0/src/sqlguard_ninja/_version.py +1 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/compare.py +8 -1
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/dataset.py +38 -2
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/metrics.py +66 -2
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/runner.py +35 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/cli/config.py +2 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/cli/main.py +162 -6
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/analysis.py +9 -1
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/findings.py +4 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/guard.py +4 -0
- sqlguard_ninja-0.3.0/src/sqlguard_ninja/core/lineage.py +199 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/rules/tenant.py +56 -25
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/integrations/audit.py +8 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/integrations/checkpoint.py +37 -4
- sqlguard_ninja-0.3.0/src/sqlguard_ninja/policy/inheritance.py +118 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/policy/model.py +47 -3
- sqlguard_ninja-0.3.0/src/sqlguard_ninja/policy/templates/analytics_readonly.yaml +31 -0
- sqlguard_ninja-0.3.0/src/sqlguard_ninja/policy/templates/minimal.yaml +17 -0
- sqlguard_ninja-0.3.0/src/sqlguard_ninja/policy/templates/multi_tenant_saas.yaml +53 -0
- sqlguard_ninja-0.3.0/src/sqlguard_ninja/policy/tools.py +410 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/privacy/rules.py +53 -14
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/reporting/markdown.py +36 -5
- sqlguard_ninja-0.3.0/src/sqlguard_ninja/tenancy.py +160 -0
- sqlguard_ninja-0.3.0/tests/security/test_tenant_rewrite.py +116 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/unit/test_benchmark_engine.py +77 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/unit/test_cli.py +47 -0
- sqlguard_ninja-0.3.0/tests/unit/test_lineage.py +84 -0
- sqlguard_ninja-0.3.0/tests/unit/test_policy_inheritance.py +162 -0
- sqlguard_ninja-0.3.0/tests/unit/test_policy_tools.py +254 -0
- sqlguard_ninja-0.1.1/src/sqlguard_ninja/_version.py +0 -1
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/.gitignore +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/LICENSE +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/THIRD_PARTY_NOTICES.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/external/README.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/cases/01_destructive.yaml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/cases/02_multi_statement_and_formatting.yaml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/cases/03_table_and_column_access.yaml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/cases/06_cte_nested_unicode.yaml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/cases/07_legitimate_lookalike_cost_dialect.yaml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/generated/grant_matrix.yaml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/generated/label_matrix.yaml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/generated/tenant_matrix.yaml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/datasets/v1/generated/transforms.yaml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/policies/retail_saas.yaml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/results/v1.0.0/agent-sql-guard.json +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/results/v1.0.0/agent-sql-guard.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/results/v1.0.0/krish2105-sqlguard.json +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/results/v1.0.0/krish2105-sqlguard.md +0 -0
- {sqlguard_ninja-0.1.1/benchmarks/baselines → sqlguard_ninja-0.3.0/benchmarks/results/v1.0.0}/native.json +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/results/v1.0.0/native.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/results/v1.0.0/sql-guardrail.json +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/benchmarks/results/v1.0.0/sql-guardrail.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/benchmarks/RESULTS_v1.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/guides/CI_INTEGRATION.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/guides/QUERY_COST.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/release/FINAL_TECHNICAL_AUDIT.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/releases/v0.1.0.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/releases/v0.1.1.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/research/COMPETITIVE_ANALYSIS.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/docs/security/STATIC_ANALYSIS_LIMITS.md +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/examples/_shared.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/examples/fastapi/app.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/examples/github-actions/sql-security.yml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/examples/langchain/guarded_tool_demo.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/examples/langgraph/real_llm_agent.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/examples/langgraph/sql_agent_demo.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/examples/postgresql/plan_inspection_demo.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/examples/sdk/quickstart.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/examples/sqlite/text_to_sql_demo.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/pyproject.toml +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/adapters.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/builtin.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/fixtures.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/translate.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/workers/_protocol.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/workers/agent_sql_guard_worker.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/workers/krish_sqlguard_worker.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/benchmarking/workers/sql_guardrail_worker.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/cli/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/cli/templates.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/rules/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/rules/access.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/rules/base.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/rules/catalog.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/rules/functions.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/rules/statements.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/core/rules/structure.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/integrations/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/integrations/executors.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/integrations/fastapi.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/integrations/langchain.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/integrations/langgraph.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/policy/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/privacy/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/privacy/suggest.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/py.typed +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/query_cost/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/query_cost/postgres.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/query_cost/static.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/src/sqlguard_ninja/reporting/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/conftest.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/integration/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/integration/test_corpus_sqlite_validation.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/integration/test_external_adapters.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/integration/test_frameworks.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/integration/test_postgres.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/pg_support.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/property/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/property/test_guard_properties.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/security/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/security/test_agent_boundaries.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/security/test_corpus_native.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/unit/__init__.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/unit/helpers.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/unit/test_dataset.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/unit/test_docs.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/unit/test_function_policy_mechanics.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/unit/test_policy.py +0 -0
- {sqlguard_ninja-0.1.1 → sqlguard_ninja-0.3.0}/tests/unit/test_rules.py +0 -0
|
@@ -3,6 +3,51 @@
|
|
|
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.3.0] — 2026-10-24
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
* **Role inheritance** (`extends`): grants merge, explicit denies are sticky, and conflicts,
|
|
10
|
+
unknown parents and cycles are load errors.
|
|
11
|
+
* **Policy metadata and identity:** `metadata.revision/owner/change_ticket`, a policy
|
|
12
|
+
fingerprint, and a per-decision `decision_id`. Audit events add `policy_revision`,
|
|
13
|
+
`policy_fingerprint`, `decision_id`, `correlation_id`, a literal-insensitive
|
|
14
|
+
`query_fingerprint`, and `tenant_filter_rewrite`.
|
|
15
|
+
* **Policy CLI:** `policy template`, `policy diff` (effect classification,
|
|
16
|
+
`--fail-on-relaxation`), `policy simulate` (`--against`, `--fail-on-change`),
|
|
17
|
+
`policy explain` (decision or column access, with inheritance source).
|
|
18
|
+
* **Templates:** `minimal`, `multi_tenant_saas`, `analytics_readonly`.
|
|
19
|
+
* **Opt-in AST tenant-filter rewrite** (`sqlguard_ninja.tenancy`,
|
|
20
|
+
`SQLCheckpoint(rewrite_tenant_filters=True)`) with re-validation and refusal rules (ADR-011).
|
|
21
|
+
* Docs: `docs/guides/POLICY_AS_CODE.md`; ADR-011, ADR-012; threat model T6a/T6b.
|
|
22
|
+
|
|
23
|
+
### Compatibility
|
|
24
|
+
* Policy files without the new fields behave exactly as before. `ValidationResult` gains
|
|
25
|
+
fields with defaults.
|
|
26
|
+
|
|
27
|
+
## [0.2.0] — 2026-10-24
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
* **Lineage-aware privacy** (`core/lineage.py`). An `aggregate_only` column projected raw in a
|
|
31
|
+
CTE or derived table is accepted only when every downstream consumer aggregates it
|
|
32
|
+
statistically. Whole-row use, filters, ordering, windows, MIN/MAX and a raw use by any
|
|
33
|
+
consumer stay denied (issue #8).
|
|
34
|
+
* **Tenant push-down.** An outer tenant pin on an unmodified projection of the tenant column
|
|
35
|
+
satisfies the inner read when the inner scope has no aggregation, window, LIMIT, OFFSET or
|
|
36
|
+
FETCH and every consumer pins it, recursively (issue #9).
|
|
37
|
+
* The small-cohort check follows identifiers through CTEs and derived tables, so the lineage
|
|
38
|
+
relaxation cannot bypass it (found by new boundary case LIN-012).
|
|
39
|
+
* Privacy findings carry structured lineage metadata (base column, JSON path, scope, labels).
|
|
40
|
+
* Benchmark: `internal` / `independent` dataset tiers, flag basis (policy vs unsupported SQL),
|
|
41
|
+
F1, 95% Wilson intervals, throughput, CSV output (`--csv`), per-file SHA-256 dataset hashes
|
|
42
|
+
in results and `sqlninja dataset stats`.
|
|
43
|
+
* Approved-relabel workflow: `LABEL_CHANGES.yaml` (CODEOWNERS-protected) lists reviewed label
|
|
44
|
+
changes; `benchmark compare --approved-label-changes` / `ci.approved_label_changes`.
|
|
45
|
+
* Corpus 1.1.0: 21 lineage boundary cases; 2 approved relabels (PRV-026, TEN-021).
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
* Decisions changed for exactly two corpus cases (PRV-026, TEN-021: deny → allow); all other
|
|
49
|
+
1,042 evaluations are unchanged.
|
|
50
|
+
|
|
6
51
|
## [0.1.1] — 2026-10-24
|
|
7
52
|
|
|
8
53
|
Documentation and governance patch. No changes to policy decisions.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sqlguard-ninja
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.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,7 +70,7 @@ 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
|
|
|
@@ -83,9 +83,9 @@ side by side.
|
|
|
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
|
|
|
@@ -246,6 +246,23 @@ Labels also apply to paths inside JSON columns (`profile->'health'->>'allergies'
|
|
|
246
246
|
suggestions are never enforced. This is a technical control, not a certification of GDPR
|
|
247
247
|
compliance. Full semantics: [POLICY_REFERENCE.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_REFERENCE.md).
|
|
248
248
|
|
|
249
|
+
## Policy as code
|
|
250
|
+
|
|
251
|
+
Roles can inherit (`extends`), and explicit denies cannot be relaxed by a child. Every decision
|
|
252
|
+
carries the policy revision, the policy fingerprint and a decision id. Review changes before
|
|
253
|
+
activating them:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
sqlninja policy template multi_tenant_saas --output policy.yaml
|
|
257
|
+
sqlninja policy diff old.yaml policy.yaml --fail-on-relaxation
|
|
258
|
+
sqlninja policy simulate --policy old.yaml --against policy.yaml --cases cases.yaml
|
|
259
|
+
sqlninja policy explain --policy policy.yaml --role support --column customers.email
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Optional: `SQLCheckpoint(..., rewrite_tenant_filters=True)` adds missing tenant filters
|
|
263
|
+
through the AST and executes only the re-validated rewrite. See
|
|
264
|
+
[POLICY_AS_CODE.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_AS_CODE.md).
|
|
265
|
+
|
|
249
266
|
## Query cost analysis
|
|
250
267
|
|
|
251
268
|
Every validation includes an explainable static score that uses the catalog's
|
|
@@ -279,22 +296,24 @@ sqlninja benchmark run --dataset builtin:v1 --adapter external:sql-guardrail
|
|
|
279
296
|
sqlninja benchmark compare --baseline benchmarks/baselines/native.json --candidate results/latest.json
|
|
280
297
|
```
|
|
281
298
|
|
|
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
|
-
|
|
299
|
+
Results for corpus v1.1.0 (551 cases, 1,044 evaluations; SQLGuard Ninja 0.2.0; Windows 11,
|
|
300
|
+
Python 3.11). Intervals are 95% Wilson intervals. Details, CSV and raw files:
|
|
301
|
+
[RESULTS_v1.1.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/benchmarks/RESULTS_v1.1.md).
|
|
302
|
+
|
|
303
|
+
| Validator | Recall (95% CI) | Precision | F1 | FPR (95% CI) | Recall / FPR within declared capability | p95 ms |
|
|
304
|
+
|---|---:|---:|---:|---:|---:|---:|
|
|
305
|
+
| 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 |
|
|
306
|
+
| 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 |
|
|
307
|
+
| 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 |
|
|
308
|
+
| 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 |
|
|
309
|
+
|
|
310
|
+
**All of these are internal results.** The corpus was written by this project, alongside the
|
|
311
|
+
engine. The native 100% shows consistency with the documented semantics, not independent
|
|
312
|
+
detection quality. No independently sourced dataset exists yet ([intake rules](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/benchmarks/datasets/external/README.md),
|
|
313
|
+
issue #6). Reports keep `internal` and `independent` tiers separate, and they also separate
|
|
314
|
+
policy denials from unsupported-SQL denials. Methodology and bias review:
|
|
315
|
+
[BENCHMARK_METHODOLOGY.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_METHODOLOGY.md),
|
|
316
|
+
[BENCHMARK_BIAS_REVIEW.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_BIAS_REVIEW.md).
|
|
298
317
|
|
|
299
318
|
## How it relates to existing tools
|
|
300
319
|
|
|
@@ -338,6 +357,7 @@ writes, more tested dialects, and SARIF output. Details in [ROADMAP.md](https://
|
|
|
338
357
|
## Documentation
|
|
339
358
|
|
|
340
359
|
* [Policy reference](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_REFERENCE.md)
|
|
360
|
+
* [Policy as code](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_AS_CODE.md)
|
|
341
361
|
* [Agent integration](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/AGENT_INTEGRATION.md)
|
|
342
362
|
* [Query cost](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/QUERY_COST.md)
|
|
343
363
|
* [CI integration](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/CI_INTEGRATION.md)
|
|
@@ -14,7 +14,7 @@ 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
|
|
|
@@ -27,9 +27,9 @@ side by side.
|
|
|
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
|
|
|
@@ -190,6 +190,23 @@ Labels also apply to paths inside JSON columns (`profile->'health'->>'allergies'
|
|
|
190
190
|
suggestions are never enforced. This is a technical control, not a certification of GDPR
|
|
191
191
|
compliance. Full semantics: [POLICY_REFERENCE.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_REFERENCE.md).
|
|
192
192
|
|
|
193
|
+
## Policy as code
|
|
194
|
+
|
|
195
|
+
Roles can inherit (`extends`), and explicit denies cannot be relaxed by a child. Every decision
|
|
196
|
+
carries the policy revision, the policy fingerprint and a decision id. Review changes before
|
|
197
|
+
activating them:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
sqlninja policy template multi_tenant_saas --output policy.yaml
|
|
201
|
+
sqlninja policy diff old.yaml policy.yaml --fail-on-relaxation
|
|
202
|
+
sqlninja policy simulate --policy old.yaml --against policy.yaml --cases cases.yaml
|
|
203
|
+
sqlninja policy explain --policy policy.yaml --role support --column customers.email
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Optional: `SQLCheckpoint(..., rewrite_tenant_filters=True)` adds missing tenant filters
|
|
207
|
+
through the AST and executes only the re-validated rewrite. See
|
|
208
|
+
[POLICY_AS_CODE.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_AS_CODE.md).
|
|
209
|
+
|
|
193
210
|
## Query cost analysis
|
|
194
211
|
|
|
195
212
|
Every validation includes an explainable static score that uses the catalog's
|
|
@@ -223,22 +240,24 @@ sqlninja benchmark run --dataset builtin:v1 --adapter external:sql-guardrail
|
|
|
223
240
|
sqlninja benchmark compare --baseline benchmarks/baselines/native.json --candidate results/latest.json
|
|
224
241
|
```
|
|
225
242
|
|
|
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
|
-
|
|
243
|
+
Results for corpus v1.1.0 (551 cases, 1,044 evaluations; SQLGuard Ninja 0.2.0; Windows 11,
|
|
244
|
+
Python 3.11). Intervals are 95% Wilson intervals. Details, CSV and raw files:
|
|
245
|
+
[RESULTS_v1.1.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/benchmarks/RESULTS_v1.1.md).
|
|
246
|
+
|
|
247
|
+
| Validator | Recall (95% CI) | Precision | F1 | FPR (95% CI) | Recall / FPR within declared capability | p95 ms |
|
|
248
|
+
|---|---:|---:|---:|---:|---:|---:|
|
|
249
|
+
| 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 |
|
|
250
|
+
| 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 |
|
|
251
|
+
| 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 |
|
|
252
|
+
| 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 |
|
|
253
|
+
|
|
254
|
+
**All of these are internal results.** The corpus was written by this project, alongside the
|
|
255
|
+
engine. The native 100% shows consistency with the documented semantics, not independent
|
|
256
|
+
detection quality. No independently sourced dataset exists yet ([intake rules](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/benchmarks/datasets/external/README.md),
|
|
257
|
+
issue #6). Reports keep `internal` and `independent` tiers separate, and they also separate
|
|
258
|
+
policy denials from unsupported-SQL denials. Methodology and bias review:
|
|
259
|
+
[BENCHMARK_METHODOLOGY.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_METHODOLOGY.md),
|
|
260
|
+
[BENCHMARK_BIAS_REVIEW.md](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/BENCHMARK_BIAS_REVIEW.md).
|
|
242
261
|
|
|
243
262
|
## How it relates to existing tools
|
|
244
263
|
|
|
@@ -282,6 +301,7 @@ writes, more tested dialects, and SARIF output. Details in [ROADMAP.md](https://
|
|
|
282
301
|
## Documentation
|
|
283
302
|
|
|
284
303
|
* [Policy reference](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_REFERENCE.md)
|
|
304
|
+
* [Policy as code](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/POLICY_AS_CODE.md)
|
|
285
305
|
* [Agent integration](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/AGENT_INTEGRATION.md)
|
|
286
306
|
* [Query cost](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/QUERY_COST.md)
|
|
287
307
|
* [CI integration](https://github.com/Pratik653/SQLGuard_Ninjapy/blob/main/docs/guides/CI_INTEGRATION.md)
|