ragfence 0.1.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.
- ragfence-0.1.0/.env.example +21 -0
- ragfence-0.1.0/.github/workflows/ci.yml +65 -0
- ragfence-0.1.0/.github/workflows/publish-pypi.yml +35 -0
- ragfence-0.1.0/.github/workflows/ragfence-test.yml +287 -0
- ragfence-0.1.0/.gitignore +33 -0
- ragfence-0.1.0/CHANGELOG.md +38 -0
- ragfence-0.1.0/CODE_OF_CONDUCT.md +20 -0
- ragfence-0.1.0/CONTRIBUTING.md +40 -0
- ragfence-0.1.0/LICENSE +201 -0
- ragfence-0.1.0/PKG-INFO +162 -0
- ragfence-0.1.0/README.md +134 -0
- ragfence-0.1.0/alembic/env.py +72 -0
- ragfence-0.1.0/alembic/script.py.mako +27 -0
- ragfence-0.1.0/alembic/versions/0001_base.py +28 -0
- ragfence-0.1.0/alembic/versions/0002_enums.py +44 -0
- ragfence-0.1.0/alembic/versions/0003_tables.py +206 -0
- ragfence-0.1.0/alembic/versions/0004_indexes.py +93 -0
- ragfence-0.1.0/alembic.ini +44 -0
- ragfence-0.1.0/docker-compose.yml +22 -0
- ragfence-0.1.0/docs/APP_FLOW.md +231 -0
- ragfence-0.1.0/docs/BACKEND_SCHEMA.md +331 -0
- ragfence-0.1.0/docs/IMPLEMENTATION_PLAN.md +406 -0
- ragfence-0.1.0/docs/PRD.md +217 -0
- ragfence-0.1.0/docs/README.md +19 -0
- ragfence-0.1.0/docs/TRD.md +415 -0
- ragfence-0.1.0/docs/UI_UX_DESIGN_BRIEF.md +150 -0
- ragfence-0.1.0/examples/generic_http.toml +15 -0
- ragfence-0.1.0/examples/reference.toml +17 -0
- ragfence-0.1.0/opencode.json +27 -0
- ragfence-0.1.0/openspec/changes/.gitkeep +1 -0
- ragfence-0.1.0/openspec/changes/archive/.gitkeep +1 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-acme-dataset/design.md +106 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-acme-dataset/proposal.md +70 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-acme-dataset/specs/synthetic-dataset/spec.md +109 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-acme-dataset/tasks.md +42 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-acme-dataset/verify-report.md +158 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-auth-context/design.md +128 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-auth-context/proposal.md +73 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-auth-context/specs/auth-context/spec.md +114 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-auth-context/tasks.md +72 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-auth-context/verify-report.md +161 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-foundation/design.md +111 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-foundation/proposal.md +77 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-foundation/specs/domain-models/spec.md +53 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-foundation/specs/policy-engine/spec.md +65 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-foundation/specs/project-bootstrap/spec.md +75 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-foundation/specs/storage-schema/spec.md +82 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-foundation/tasks.md +51 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-foundation/verify-report.md +176 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-secure-retrieval/design.md +101 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-secure-retrieval/proposal.md +74 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-secure-retrieval/specs/secure-retrieval/spec.md +95 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-secure-retrieval/tasks.md +53 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-13-ragfence-secure-retrieval/verify-report.md +148 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-attack-engine/apply-progress.md +32 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-attack-engine/build-output.txt +4 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-attack-engine/design.md +78 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-attack-engine/proposal.md +49 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-attack-engine/specs/attack-engine/spec.md +80 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-attack-engine/tasks.md +40 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-attack-engine/test-output.txt +20 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-attack-engine/verify-report.md +71 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-cli/apply-progress.md +28 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-cli/build-output.txt +4 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-cli/design.md +59 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-cli/proposal.md +48 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-cli/specs/cli/spec.md +117 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-cli/tasks.md +41 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-cli/test-output.txt +19 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-cli/verify-report.md +73 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-evaluation/apply-progress.md +67 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-evaluation/build-output.txt +4 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-evaluation/design.md +69 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-evaluation/proposal.md +42 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-evaluation/specs/evaluation/spec.md +156 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-evaluation/tasks.md +65 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-evaluation/test-output.txt +5 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-17-ragfence-evaluation/verify-report.md +88 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-ci-integration/apply-progress.md +19 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-ci-integration/build-output.txt +4 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-ci-integration/design.md +68 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-ci-integration/proposal.md +41 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-ci-integration/specs/ci-integration/spec.md +155 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-ci-integration/tasks.md +48 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-ci-integration/test-output.txt +7 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-ci-integration/verify-report.md +60 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-generic-http/apply-progress.md +35 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-generic-http/build-output.txt +4 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-generic-http/design.md +72 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-generic-http/proposal.md +38 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-generic-http/specs/generic-http/spec.md +163 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-generic-http/tasks.md +59 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-generic-http/test-output.txt +6 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-generic-http/verify-report.md +69 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-llm-providers/apply-progress.md +24 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-llm-providers/build-output.txt +4 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-llm-providers/design.md +55 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-llm-providers/proposal.md +37 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-llm-providers/specs/llm-providers/spec.md +162 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-llm-providers/tasks.md +59 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-llm-providers/test-output.txt +7 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-llm-providers/verify-report.md +63 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-release-readiness/apply-progress.md +39 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-release-readiness/build-output.txt +4 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-release-readiness/design.md +35 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-release-readiness/proposal.md +42 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-release-readiness/specs/release-readiness/spec.md +119 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-release-readiness/tasks.md +58 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-release-readiness/test-output.txt +7 -0
- ragfence-0.1.0/openspec/changes/archive/2026-08-18-ragfence-release-readiness/verify-report.md +60 -0
- ragfence-0.1.0/openspec/changes/ragfence-production-e2e/design.md +19 -0
- ragfence-0.1.0/openspec/changes/ragfence-production-e2e/proposal.md +23 -0
- ragfence-0.1.0/openspec/changes/ragfence-production-e2e/specs/production-e2e/spec.md +77 -0
- ragfence-0.1.0/openspec/changes/ragfence-production-e2e/tasks.md +11 -0
- ragfence-0.1.0/openspec/config.yaml +50 -0
- ragfence-0.1.0/openspec/specs/.gitkeep +1 -0
- ragfence-0.1.0/openspec/specs/auth-context/spec.md +114 -0
- ragfence-0.1.0/openspec/specs/domain-models/spec.md +53 -0
- ragfence-0.1.0/openspec/specs/policy-engine/spec.md +65 -0
- ragfence-0.1.0/openspec/specs/project-bootstrap/spec.md +75 -0
- ragfence-0.1.0/openspec/specs/secure-retrieval/spec.md +95 -0
- ragfence-0.1.0/openspec/specs/storage-schema/spec.md +82 -0
- ragfence-0.1.0/openspec/specs/synthetic-dataset/spec.md +109 -0
- ragfence-0.1.0/pyproject.toml +67 -0
- ragfence-0.1.0/src/ragfence/__init__.py +3 -0
- ragfence-0.1.0/src/ragfence/adapters/__init__.py +6 -0
- ragfence-0.1.0/src/ragfence/adapters/errors.py +38 -0
- ragfence-0.1.0/src/ragfence/adapters/factory.py +16 -0
- ragfence-0.1.0/src/ragfence/adapters/generic_http.py +466 -0
- ragfence-0.1.0/src/ragfence/adapters/mapping.py +67 -0
- ragfence-0.1.0/src/ragfence/adapters/models.py +38 -0
- ragfence-0.1.0/src/ragfence/adapters/reference.py +154 -0
- ragfence-0.1.0/src/ragfence/adapters/wire.py +57 -0
- ragfence-0.1.0/src/ragfence/attacks/__init__.py +17 -0
- ragfence-0.1.0/src/ragfence/attacks/generators.py +301 -0
- ragfence-0.1.0/src/ragfence/attacks/runner.py +131 -0
- ragfence-0.1.0/src/ragfence/attacks/scenarios.py +83 -0
- ragfence-0.1.0/src/ragfence/auth/__init__.py +33 -0
- ragfence-0.1.0/src/ragfence/auth/builder.py +32 -0
- ragfence-0.1.0/src/ragfence/auth/db.py +86 -0
- ragfence-0.1.0/src/ragfence/auth/errors.py +18 -0
- ragfence-0.1.0/src/ragfence/auth/identity.py +31 -0
- ragfence-0.1.0/src/ragfence/auth/providers.py +78 -0
- ragfence-0.1.0/src/ragfence/auth/registry.py +28 -0
- ragfence-0.1.0/src/ragfence/cli/__init__.py +1 -0
- ragfence-0.1.0/src/ragfence/cli/config.py +93 -0
- ragfence-0.1.0/src/ragfence/cli/errors.py +9 -0
- ragfence-0.1.0/src/ragfence/cli/main.py +227 -0
- ragfence-0.1.0/src/ragfence/cli/reporting.py +89 -0
- ragfence-0.1.0/src/ragfence/cli/seams.py +211 -0
- ragfence-0.1.0/src/ragfence/core/__init__.py +1 -0
- ragfence-0.1.0/src/ragfence/core/enums.py +48 -0
- ragfence-0.1.0/src/ragfence/core/models.py +177 -0
- ragfence-0.1.0/src/ragfence/core/protocols.py +49 -0
- ragfence-0.1.0/src/ragfence/datasets/__init__.py +28 -0
- ragfence-0.1.0/src/ragfence/datasets/acme.py +373 -0
- ragfence-0.1.0/src/ragfence/datasets/checksums.py +27 -0
- ragfence-0.1.0/src/ragfence/datasets/constants.py +90 -0
- ragfence-0.1.0/src/ragfence/datasets/loader.py +233 -0
- ragfence-0.1.0/src/ragfence/db/__init__.py +1 -0
- ragfence-0.1.0/src/ragfence/db/base.py +12 -0
- ragfence-0.1.0/src/ragfence/db/models.py +509 -0
- ragfence-0.1.0/src/ragfence/db/repositories.py +152 -0
- ragfence-0.1.0/src/ragfence/db/vector_store.py +82 -0
- ragfence-0.1.0/src/ragfence/evaluation/__init__.py +1 -0
- ragfence-0.1.0/src/ragfence/evaluation/contracts.py +58 -0
- ragfence-0.1.0/src/ragfence/evaluation/engine.py +377 -0
- ragfence-0.1.0/src/ragfence/evaluation/findings.py +154 -0
- ragfence-0.1.0/src/ragfence/evaluation/gate.py +117 -0
- ragfence-0.1.0/src/ragfence/evaluation/matrix_runner.py +315 -0
- ragfence-0.1.0/src/ragfence/evaluation/metrics.py +152 -0
- ragfence-0.1.0/src/ragfence/evaluation/redaction.py +105 -0
- ragfence-0.1.0/src/ragfence/evaluation/report.py +166 -0
- ragfence-0.1.0/src/ragfence/evaluation/repositories.py +353 -0
- ragfence-0.1.0/src/ragfence/evaluation/scoring.py +83 -0
- ragfence-0.1.0/src/ragfence/observability/__init__.py +1 -0
- ragfence-0.1.0/src/ragfence/policies/__init__.py +1 -0
- ragfence-0.1.0/src/ragfence/policies/decision.py +52 -0
- ragfence-0.1.0/src/ragfence/policies/guard.py +80 -0
- ragfence-0.1.0/src/ragfence/providers/__init__.py +21 -0
- ragfence-0.1.0/src/ragfence/providers/errors.py +24 -0
- ragfence-0.1.0/src/ragfence/providers/fakes.py +51 -0
- ragfence-0.1.0/src/ragfence/providers/llm.py +466 -0
- ragfence-0.1.0/src/ragfence/providers/tokens.py +23 -0
- ragfence-0.1.0/src/ragfence/providers/transport.py +85 -0
- ragfence-0.1.0/src/ragfence/reference/alembic/env.py +72 -0
- ragfence-0.1.0/src/ragfence/reference/alembic/script.py.mako +27 -0
- ragfence-0.1.0/src/ragfence/reference/alembic/versions/0001_base.py +28 -0
- ragfence-0.1.0/src/ragfence/reference/alembic/versions/0002_enums.py +44 -0
- ragfence-0.1.0/src/ragfence/reference/alembic/versions/0003_tables.py +206 -0
- ragfence-0.1.0/src/ragfence/reference/alembic/versions/0004_indexes.py +93 -0
- ragfence-0.1.0/src/ragfence/reference/alembic.ini +44 -0
- ragfence-0.1.0/src/ragfence/reference/docker-compose.yml +22 -0
- ragfence-0.1.0/src/ragfence/release_readiness/__init__.py +1 -0
- ragfence-0.1.0/src/ragfence/release_readiness/audit.py +113 -0
- ragfence-0.1.0/src/ragfence/release_readiness/benchmark.py +97 -0
- ragfence-0.1.0/src/ragfence/release_readiness/checklist.py +79 -0
- ragfence-0.1.0/src/ragfence/retrieval/__init__.py +32 -0
- ragfence-0.1.0/src/ragfence/retrieval/citations.py +54 -0
- ragfence-0.1.0/src/ragfence/retrieval/result.py +39 -0
- ragfence-0.1.0/src/ragfence/retrieval/service.py +144 -0
- ragfence-0.1.0/src/ragfence/retrieval/trace.py +24 -0
- ragfence-0.1.0/tests/__init__.py +0 -0
- ragfence-0.1.0/tests/conftest.py +48 -0
- ragfence-0.1.0/tests/fixtures/ci_report.json +17 -0
- ragfence-0.1.0/tests/integration/__init__.py +3 -0
- ragfence-0.1.0/tests/integration/conftest.py +38 -0
- ragfence-0.1.0/tests/integration/test_auth_db.py +121 -0
- ragfence-0.1.0/tests/integration/test_datasets_seed.py +140 -0
- ragfence-0.1.0/tests/integration/test_evaluation_e2e_db.py +209 -0
- ragfence-0.1.0/tests/integration/test_evaluation_persistence_g2_g4_db.py +101 -0
- ragfence-0.1.0/tests/integration/test_generic_http_stub.py +184 -0
- ragfence-0.1.0/tests/integration/test_migrations.py +254 -0
- ragfence-0.1.0/tests/integration/test_reference_adapter.py +76 -0
- ragfence-0.1.0/tests/integration/test_release_e2e_db.py +72 -0
- ragfence-0.1.0/tests/integration/test_retrieval_db.py +275 -0
- ragfence-0.1.0/tests/support/__init__.py +0 -0
- ragfence-0.1.0/tests/support/generic_http_stub.py +91 -0
- ragfence-0.1.0/tests/support/vector_store.py +83 -0
- ragfence-0.1.0/tests/test_acl.py +135 -0
- ragfence-0.1.0/tests/test_attack_generators.py +71 -0
- ragfence-0.1.0/tests/test_attack_runner.py +185 -0
- ragfence-0.1.0/tests/test_attack_scenarios.py +31 -0
- ragfence-0.1.0/tests/test_auth_builder.py +137 -0
- ragfence-0.1.0/tests/test_auth_db.py +138 -0
- ragfence-0.1.0/tests/test_auth_errors.py +45 -0
- ragfence-0.1.0/tests/test_auth_providers.py +124 -0
- ragfence-0.1.0/tests/test_auth_registry.py +84 -0
- ragfence-0.1.0/tests/test_bootstrap.py +38 -0
- ragfence-0.1.0/tests/test_ci.py +62 -0
- ragfence-0.1.0/tests/test_ci_workflow_structure.py +229 -0
- ragfence-0.1.0/tests/test_cli.py +78 -0
- ragfence-0.1.0/tests/test_cli_config.py +41 -0
- ragfence-0.1.0/tests/test_cli_reporting.py +292 -0
- ragfence-0.1.0/tests/test_compose.py +44 -0
- ragfence-0.1.0/tests/test_datasets_determinism.py +103 -0
- ragfence-0.1.0/tests/test_datasets_loader.py +175 -0
- ragfence-0.1.0/tests/test_datasets_org.py +118 -0
- ragfence-0.1.0/tests/test_datasets_security.py +122 -0
- ragfence-0.1.0/tests/test_db_gating.py +53 -0
- ragfence-0.1.0/tests/test_decision.py +144 -0
- ragfence-0.1.0/tests/test_enums.py +53 -0
- ragfence-0.1.0/tests/test_evaluation_cli_seam.py +130 -0
- ragfence-0.1.0/tests/test_evaluation_contracts.py +36 -0
- ragfence-0.1.0/tests/test_evaluation_control_matrix.py +115 -0
- ragfence-0.1.0/tests/test_evaluation_engine.py +134 -0
- ragfence-0.1.0/tests/test_evaluation_findings.py +85 -0
- ragfence-0.1.0/tests/test_evaluation_gate.py +187 -0
- ragfence-0.1.0/tests/test_evaluation_generation_gating.py +168 -0
- ragfence-0.1.0/tests/test_evaluation_metrics.py +68 -0
- ragfence-0.1.0/tests/test_evaluation_persistence.py +131 -0
- ragfence-0.1.0/tests/test_evaluation_redaction.py +68 -0
- ragfence-0.1.0/tests/test_evaluation_report.py +101 -0
- ragfence-0.1.0/tests/test_evaluation_repositories.py +214 -0
- ragfence-0.1.0/tests/test_evaluation_scoring.py +37 -0
- ragfence-0.1.0/tests/test_generic_http_adapter.py +122 -0
- ragfence-0.1.0/tests/test_generic_http_cli.py +107 -0
- ragfence-0.1.0/tests/test_generic_http_config.py +90 -0
- ragfence-0.1.0/tests/test_generic_http_mapping.py +124 -0
- ragfence-0.1.0/tests/test_generic_http_transport.py +182 -0
- ragfence-0.1.0/tests/test_generic_http_wire.py +75 -0
- ragfence-0.1.0/tests/test_guard.py +182 -0
- ragfence-0.1.0/tests/test_identity_adapter.py +127 -0
- ragfence-0.1.0/tests/test_identity_config.py +80 -0
- ragfence-0.1.0/tests/test_identity_secrets_hygiene.py +397 -0
- ragfence-0.1.0/tests/test_llm_config.py +117 -0
- ragfence-0.1.0/tests/test_llm_end_to_end.py +240 -0
- ragfence-0.1.0/tests/test_llm_transport.py +157 -0
- ragfence-0.1.0/tests/test_matrix_runner.py +197 -0
- ragfence-0.1.0/tests/test_migration_ddl.py +87 -0
- ragfence-0.1.0/tests/test_models.py +258 -0
- ragfence-0.1.0/tests/test_protocols.py +122 -0
- ragfence-0.1.0/tests/test_release_basics.py +77 -0
- ragfence-0.1.0/tests/test_release_e2e.py +69 -0
- ragfence-0.1.0/tests/test_release_packaging.py +131 -0
- ragfence-0.1.0/tests/test_release_readiness_docs.py +49 -0
- ragfence-0.1.0/tests/test_release_readiness_examples.py +98 -0
- ragfence-0.1.0/tests/test_release_work_units_6_9.py +69 -0
- ragfence-0.1.0/tests/test_repositories.py +214 -0
- ragfence-0.1.0/tests/test_schema_metadata.py +511 -0
- ragfence-0.1.0/tests/test_secure_retrieval.py +304 -0
- ragfence-0.1.0/uv.lock +921 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# RAGFence environment configuration template.
|
|
2
|
+
# Copy this file to `.env` and fill in real values for your environment.
|
|
3
|
+
# NEVER commit real credentials. Every value below is a placeholder.
|
|
4
|
+
|
|
5
|
+
# PostgreSQL DSN for the reference implementation (see docs/TRD.md, Section 11).
|
|
6
|
+
RAGFENCE_DATABASE_DSN=postgresql+psycopg://ragfence:CHANGEME@localhost:5432/ragfence
|
|
7
|
+
|
|
8
|
+
# Embedding dimension for pgvector columns (TRD default: 1536).
|
|
9
|
+
RAGFENCE_EMBEDDING_DIM=1536
|
|
10
|
+
|
|
11
|
+
# Default evaluation pass threshold (0-100).
|
|
12
|
+
RAGFENCE_EVALUATION_THRESHOLD=80
|
|
13
|
+
|
|
14
|
+
# Optional BYOK provider keys (see docs/TRD.md, Section 10).
|
|
15
|
+
# Leave unset to use the fake default providers with zero external dependencies.
|
|
16
|
+
RAGFENCE_LLM_API_KEY=CHANGEME
|
|
17
|
+
RAGFENCE_EMBEDDING_API_KEY=CHANGEME
|
|
18
|
+
|
|
19
|
+
# Optional OIDC identity provider settings for `auth` (synthetic source otherwise).
|
|
20
|
+
RAGFENCE_OIDC_ISSUER=CHANGEME
|
|
21
|
+
RAGFENCE_OIDC_CLIENT_ID=CHANGEME
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
ci:
|
|
13
|
+
name: Lint, type, and test
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ["3.12"]
|
|
18
|
+
services:
|
|
19
|
+
postgres:
|
|
20
|
+
image: pgvector/pgvector:pg16
|
|
21
|
+
env:
|
|
22
|
+
POSTGRES_USER: ragfence
|
|
23
|
+
POSTGRES_PASSWORD: ragfence
|
|
24
|
+
POSTGRES_DB: ragfence
|
|
25
|
+
ports:
|
|
26
|
+
- 5434:5432
|
|
27
|
+
options: >-
|
|
28
|
+
--health-cmd "pg_isready -U ragfence -d ragfence"
|
|
29
|
+
--health-interval 10s
|
|
30
|
+
--health-timeout 5s
|
|
31
|
+
--health-retries 5
|
|
32
|
+
env:
|
|
33
|
+
RAGFENCE_TEST_DATABASE_DSN: postgresql+psycopg://ragfence:ragfence@localhost:5434/ragfence
|
|
34
|
+
steps:
|
|
35
|
+
- name: Checkout
|
|
36
|
+
uses: actions/checkout@v4
|
|
37
|
+
|
|
38
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
39
|
+
uses: actions/setup-python@v5
|
|
40
|
+
with:
|
|
41
|
+
python-version: ${{ matrix.python-version }}
|
|
42
|
+
|
|
43
|
+
- name: Install dependencies
|
|
44
|
+
run: |
|
|
45
|
+
python -m pip install --upgrade pip
|
|
46
|
+
python -m pip install -e ".[dev]"
|
|
47
|
+
|
|
48
|
+
- name: Migrate database schema
|
|
49
|
+
run: alembic upgrade head
|
|
50
|
+
|
|
51
|
+
- name: Seed reference database
|
|
52
|
+
run: |
|
|
53
|
+
python -c "from sqlalchemy import create_engine; from sqlalchemy.orm import Session; from ragfence.datasets import seed_reference_corp; import os; engine = create_engine(os.environ['RAGFENCE_TEST_DATABASE_DSN']); sess = Session(engine); seed_reference_corp(sess); sess.commit(); engine.dispose()"
|
|
54
|
+
|
|
55
|
+
- name: Lint (ruff check)
|
|
56
|
+
run: ruff check .
|
|
57
|
+
|
|
58
|
+
- name: Format (ruff format --check)
|
|
59
|
+
run: ruff format --check .
|
|
60
|
+
|
|
61
|
+
- name: Type check (mypy)
|
|
62
|
+
run: mypy
|
|
63
|
+
|
|
64
|
+
- name: Tests (pytest)
|
|
65
|
+
run: python -m pytest
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
name: Build and publish distribution
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
environment:
|
|
17
|
+
name: pypi
|
|
18
|
+
url: https://pypi.org/p/ragfence
|
|
19
|
+
steps:
|
|
20
|
+
- name: Check out release source
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Set up Python
|
|
24
|
+
uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: "3.12"
|
|
27
|
+
|
|
28
|
+
- name: Install build tooling
|
|
29
|
+
run: python -m pip install --upgrade build
|
|
30
|
+
|
|
31
|
+
- name: Build wheel and source distribution
|
|
32
|
+
run: python -m build
|
|
33
|
+
|
|
34
|
+
- name: Publish distributions with PyPI Trusted Publishing
|
|
35
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
name: RAGFence test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
inputs:
|
|
6
|
+
adapter:
|
|
7
|
+
description: Adapter passed to ragfence test
|
|
8
|
+
type: string
|
|
9
|
+
required: false
|
|
10
|
+
default: reference
|
|
11
|
+
target:
|
|
12
|
+
description: Target service name
|
|
13
|
+
type: string
|
|
14
|
+
required: false
|
|
15
|
+
default: target
|
|
16
|
+
base-url:
|
|
17
|
+
description: Target base URL
|
|
18
|
+
type: string
|
|
19
|
+
required: false
|
|
20
|
+
default: ""
|
|
21
|
+
threshold:
|
|
22
|
+
description: Inclusive score threshold from 0 to 100
|
|
23
|
+
type: number
|
|
24
|
+
required: false
|
|
25
|
+
default: 80
|
|
26
|
+
start-target-command:
|
|
27
|
+
description: Quoted command used to start the target service
|
|
28
|
+
type: string
|
|
29
|
+
required: false
|
|
30
|
+
default: ""
|
|
31
|
+
comment:
|
|
32
|
+
description: Enable the trusted same-repository PR comment path
|
|
33
|
+
type: boolean
|
|
34
|
+
required: false
|
|
35
|
+
default: true
|
|
36
|
+
fake-providers:
|
|
37
|
+
description: Use deterministic local fake providers
|
|
38
|
+
type: boolean
|
|
39
|
+
required: false
|
|
40
|
+
default: true
|
|
41
|
+
|
|
42
|
+
permissions:
|
|
43
|
+
contents: read
|
|
44
|
+
actions: read
|
|
45
|
+
|
|
46
|
+
jobs:
|
|
47
|
+
ragfence-test:
|
|
48
|
+
name: RAGFence evaluation (Python ${{ matrix.python-version }})
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
strategy:
|
|
51
|
+
matrix:
|
|
52
|
+
python-version: ["3.12"]
|
|
53
|
+
services:
|
|
54
|
+
postgres:
|
|
55
|
+
image: pgvector/pgvector:pg16
|
|
56
|
+
env:
|
|
57
|
+
POSTGRES_USER: ragfence
|
|
58
|
+
POSTGRES_PASSWORD: ragfence
|
|
59
|
+
POSTGRES_DB: ragfence
|
|
60
|
+
ports:
|
|
61
|
+
- 5434:5432
|
|
62
|
+
options: >-
|
|
63
|
+
--health-cmd "pg_isready -U ragfence -d ragfence"
|
|
64
|
+
--health-interval 10s
|
|
65
|
+
--health-timeout 5s
|
|
66
|
+
--health-retries 5
|
|
67
|
+
env:
|
|
68
|
+
REPORT_PATH: .ragfence/reports/ci.json
|
|
69
|
+
ARTIFACT_NAME: ragfence-report-${{ matrix.python-version }}
|
|
70
|
+
ADAPTER: ${{ inputs.adapter }}
|
|
71
|
+
TARGET: ${{ inputs.target }}
|
|
72
|
+
BASE_URL: ${{ inputs.base-url }}
|
|
73
|
+
THRESHOLD: ${{ inputs.threshold }}
|
|
74
|
+
START_TARGET_COMMAND: ${{ inputs.start-target-command }}
|
|
75
|
+
FAKE_PROVIDERS: ${{ inputs.fake-providers }}
|
|
76
|
+
RAGFENCE_TEST_DATABASE_DSN: postgresql+psycopg://ragfence:ragfence@localhost:5434/ragfence
|
|
77
|
+
steps:
|
|
78
|
+
- name: Checkout
|
|
79
|
+
uses: actions/checkout@v4
|
|
80
|
+
|
|
81
|
+
- name: Set up Python
|
|
82
|
+
uses: actions/setup-python@v5
|
|
83
|
+
with:
|
|
84
|
+
python-version: ${{ matrix.python-version }}
|
|
85
|
+
|
|
86
|
+
- name: Install dependencies
|
|
87
|
+
run: |
|
|
88
|
+
python -m pip install --upgrade pip
|
|
89
|
+
python -m pip install -e ".[dev]"
|
|
90
|
+
|
|
91
|
+
- name: Validate inputs
|
|
92
|
+
env:
|
|
93
|
+
INPUT_ADAPTER: ${{ inputs.adapter }}
|
|
94
|
+
INPUT_TARGET: ${{ inputs.target }}
|
|
95
|
+
INPUT_BASE_URL: ${{ inputs.base-url }}
|
|
96
|
+
INPUT_THRESHOLD: ${{ inputs.threshold }}
|
|
97
|
+
INPUT_START_COMMAND: ${{ inputs.start-target-command }}
|
|
98
|
+
run: |
|
|
99
|
+
python - <<'PY'
|
|
100
|
+
import math
|
|
101
|
+
import os
|
|
102
|
+
from urllib.parse import urlparse
|
|
103
|
+
|
|
104
|
+
adapter = os.environ["INPUT_ADAPTER"].strip()
|
|
105
|
+
target = os.environ["INPUT_TARGET"].strip()
|
|
106
|
+
base_url = os.environ["INPUT_BASE_URL"].strip()
|
|
107
|
+
start_command = os.environ["INPUT_START_COMMAND"].strip()
|
|
108
|
+
try:
|
|
109
|
+
threshold = float(os.environ["INPUT_THRESHOLD"])
|
|
110
|
+
except ValueError as error:
|
|
111
|
+
raise SystemExit("Invalid threshold configuration.") from error
|
|
112
|
+
if not adapter or not target:
|
|
113
|
+
raise SystemExit("Invalid RAGFence CI input configuration.")
|
|
114
|
+
if adapter == "generic_http":
|
|
115
|
+
parsed = urlparse(base_url)
|
|
116
|
+
if not start_command or parsed.scheme not in {"http", "https"} or not parsed.netloc:
|
|
117
|
+
raise SystemExit("Invalid RAGFence CI input configuration.")
|
|
118
|
+
if not math.isfinite(threshold) or not 0 <= threshold <= 100:
|
|
119
|
+
raise SystemExit("threshold must satisfy 0 <= threshold <= 100")
|
|
120
|
+
PY
|
|
121
|
+
|
|
122
|
+
- name: Initialize RAGFence
|
|
123
|
+
run: |
|
|
124
|
+
mkdir -p .ragfence/reports
|
|
125
|
+
ragfence init
|
|
126
|
+
|
|
127
|
+
- name: Migrate and seed reference database
|
|
128
|
+
run: |
|
|
129
|
+
alembic upgrade head
|
|
130
|
+
python -c "from sqlalchemy import create_engine; from sqlalchemy.orm import Session; from ragfence.datasets import seed_reference_corp; import os; engine = create_engine(os.environ['RAGFENCE_TEST_DATABASE_DSN']); sess = Session(engine); seed_reference_corp(sess); sess.commit(); engine.dispose()"
|
|
131
|
+
|
|
132
|
+
- name: Start target
|
|
133
|
+
if: ${{ inputs.start-target-command != '' }}
|
|
134
|
+
run: |
|
|
135
|
+
bash -c -- "$START_TARGET_COMMAND" >.ragfence/target-start.log 2>&1 &
|
|
136
|
+
printf '%s\n' "$!" > .ragfence/target.pid
|
|
137
|
+
|
|
138
|
+
- name: Wait for target readiness
|
|
139
|
+
if: ${{ inputs.start-target-command != '' && inputs.base-url != '' }}
|
|
140
|
+
env:
|
|
141
|
+
READINESS_ATTEMPTS: 30
|
|
142
|
+
READINESS_DELAY_SECONDS: 2
|
|
143
|
+
run: |
|
|
144
|
+
python - <<'PY'
|
|
145
|
+
import os
|
|
146
|
+
import sys
|
|
147
|
+
import time
|
|
148
|
+
import urllib.error
|
|
149
|
+
import urllib.request
|
|
150
|
+
|
|
151
|
+
url = os.environ["BASE_URL"]
|
|
152
|
+
attempts = int(os.environ["READINESS_ATTEMPTS"])
|
|
153
|
+
delay = int(os.environ["READINESS_DELAY_SECONDS"])
|
|
154
|
+
for attempt in range(attempts):
|
|
155
|
+
try:
|
|
156
|
+
with urllib.request.urlopen(url, timeout=2) as response:
|
|
157
|
+
if response.status < 500:
|
|
158
|
+
raise SystemExit(0)
|
|
159
|
+
except (OSError, urllib.error.URLError):
|
|
160
|
+
pass
|
|
161
|
+
if attempt + 1 < attempts:
|
|
162
|
+
time.sleep(delay)
|
|
163
|
+
print("Target readiness check failed after bounded retries.", file=sys.stderr)
|
|
164
|
+
raise SystemExit(2)
|
|
165
|
+
PY
|
|
166
|
+
|
|
167
|
+
- name: Evaluate target
|
|
168
|
+
id: evaluate
|
|
169
|
+
env:
|
|
170
|
+
CLI_THRESHOLD: ${{ inputs.threshold }}
|
|
171
|
+
run: |
|
|
172
|
+
set +e
|
|
173
|
+
if [ "$FAKE_PROVIDERS" = "true" ]; then
|
|
174
|
+
export RAGFENCE_LLM_PROVIDER=fake
|
|
175
|
+
export RAGFENCE_EMBEDDING_PROVIDER=fake
|
|
176
|
+
fi
|
|
177
|
+
LEGACY_THRESHOLD=$(python -c "print(float('$CLI_THRESHOLD') / 100.0)")
|
|
178
|
+
if [ "$ADAPTER" = "generic_http" ]; then
|
|
179
|
+
ragfence test --adapter "$ADAPTER" --base-url "$BASE_URL" --threshold "$LEGACY_THRESHOLD" --json --output "$REPORT_PATH"
|
|
180
|
+
else
|
|
181
|
+
ragfence test --adapter "$ADAPTER" --threshold "$LEGACY_THRESHOLD" --json --output "$REPORT_PATH"
|
|
182
|
+
fi
|
|
183
|
+
cli_status=$?
|
|
184
|
+
set -e
|
|
185
|
+
case "$cli_status" in
|
|
186
|
+
0|1|2) ;;
|
|
187
|
+
*) cli_status=2 ;;
|
|
188
|
+
esac
|
|
189
|
+
if [ -s "$REPORT_PATH" ]; then report_exists=true; else report_exists=false; fi
|
|
190
|
+
{
|
|
191
|
+
printf 'status=%s\n' "$cli_status"
|
|
192
|
+
printf 'report_exists=%s\n' "$report_exists"
|
|
193
|
+
} >> "$GITHUB_OUTPUT"
|
|
194
|
+
exit "$cli_status"
|
|
195
|
+
|
|
196
|
+
- name: Upload JSON report
|
|
197
|
+
if: always()
|
|
198
|
+
uses: actions/upload-artifact@v4
|
|
199
|
+
with:
|
|
200
|
+
name: ${{ env.ARTIFACT_NAME }}
|
|
201
|
+
path: ${{ env.REPORT_PATH }}
|
|
202
|
+
if-no-files-found: error
|
|
203
|
+
retention-days: 14
|
|
204
|
+
|
|
205
|
+
- name: Write job summary
|
|
206
|
+
if: always()
|
|
207
|
+
env:
|
|
208
|
+
CLI_STATUS: ${{ steps.evaluate.outputs.status || '2' }}
|
|
209
|
+
REPORT_EXISTS: ${{ steps.evaluate.outputs.report_exists || 'false' }}
|
|
210
|
+
run: |
|
|
211
|
+
: "${GITHUB_STEP_SUMMARY:?summary file is required}"
|
|
212
|
+
python - <<'PY'
|
|
213
|
+
import json
|
|
214
|
+
import os
|
|
215
|
+
from pathlib import Path
|
|
216
|
+
|
|
217
|
+
path = Path(os.environ["REPORT_PATH"])
|
|
218
|
+
status = int(os.environ["CLI_STATUS"])
|
|
219
|
+
exists = os.environ["REPORT_EXISTS"] == "true" and path.is_file()
|
|
220
|
+
score = "unavailable"
|
|
221
|
+
outcome = "execution/configuration error"
|
|
222
|
+
passed = "false"
|
|
223
|
+
if exists:
|
|
224
|
+
try:
|
|
225
|
+
report = json.loads(path.read_text(encoding="utf-8"))
|
|
226
|
+
score_value = report.get("score")
|
|
227
|
+
if isinstance(score_value, (int, float)):
|
|
228
|
+
score = str(score_value)[:32]
|
|
229
|
+
outcome_value = report.get("outcome")
|
|
230
|
+
if isinstance(outcome_value, str):
|
|
231
|
+
outcome = outcome_value[:80]
|
|
232
|
+
passed_value = report.get("gate_passed")
|
|
233
|
+
if passed_value is None:
|
|
234
|
+
passed_value = report.get("passed_threshold")
|
|
235
|
+
if isinstance(passed_value, bool):
|
|
236
|
+
passed = str(passed_value).lower()
|
|
237
|
+
except (OSError, ValueError, TypeError):
|
|
238
|
+
outcome = "execution/configuration error"
|
|
239
|
+
if status == 1 and outcome == "execution/configuration error":
|
|
240
|
+
outcome = "below threshold"
|
|
241
|
+
summary = [
|
|
242
|
+
"## RAGFence evaluation",
|
|
243
|
+
"",
|
|
244
|
+
f"- Score: `{score}`",
|
|
245
|
+
f"- Threshold: `{os.environ['THRESHOLD'][:32]}`",
|
|
246
|
+
f"- Outcome: `{outcome}`",
|
|
247
|
+
f"- Passed threshold: `{passed}`",
|
|
248
|
+
f"- CLI exit status: `{status}`",
|
|
249
|
+
f"- Report: `{os.environ['REPORT_PATH']}`",
|
|
250
|
+
f"- Artifact: `{os.environ['ARTIFACT_NAME']}`",
|
|
251
|
+
]
|
|
252
|
+
with Path(os.environ["GITHUB_STEP_SUMMARY"]).open("a", encoding="utf-8") as handle:
|
|
253
|
+
handle.write("\n".join(summary) + "\n")
|
|
254
|
+
PY
|
|
255
|
+
|
|
256
|
+
- name: Comment on trusted same-repository PR
|
|
257
|
+
if: ${{ inputs.comment && github.event_name == 'pull_request' && github.event_name != 'pull_request_target' && github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.base.repo.full_name == github.repository }}
|
|
258
|
+
uses: actions/github-script@v7
|
|
259
|
+
env:
|
|
260
|
+
CLI_STATUS: ${{ steps.evaluate.outputs.status || '2' }}
|
|
261
|
+
REPORT_PATH: ${{ env.REPORT_PATH }}
|
|
262
|
+
with:
|
|
263
|
+
script: |
|
|
264
|
+
const marker = '<!-- ragfence-ci-summary -->';
|
|
265
|
+
const body = `${marker}\n## RAGFence evaluation\n- CLI exit status: ${process.env.CLI_STATUS}\n- Report artifact: ${process.env.REPORT_PATH}`;
|
|
266
|
+
const { owner, repo } = context.repo;
|
|
267
|
+
const issue_number = context.issue.number;
|
|
268
|
+
const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, issue_number, per_page: 100 });
|
|
269
|
+
const existing = comments.find((comment) => comment.body && comment.body.includes(marker));
|
|
270
|
+
if (existing) {
|
|
271
|
+
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
|
|
272
|
+
} else {
|
|
273
|
+
await github.rest.issues.createComment({ owner, repo, issue_number, body });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
- name: Final gate
|
|
277
|
+
if: always()
|
|
278
|
+
env:
|
|
279
|
+
CLI_STATUS: ${{ steps.evaluate.outputs.status || '2' }}
|
|
280
|
+
REPORT_EXISTS: ${{ steps.evaluate.outputs.report_exists || 'false' }}
|
|
281
|
+
run: |
|
|
282
|
+
status="$CLI_STATUS"
|
|
283
|
+
if [ "$REPORT_EXISTS" != "true" ]; then status=2; fi
|
|
284
|
+
case "$status" in
|
|
285
|
+
0|1|2) exit "$status" ;;
|
|
286
|
+
*) exit 2 ;;
|
|
287
|
+
esac
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Python bytecode and build artifacts
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
env/
|
|
13
|
+
|
|
14
|
+
# Tooling caches
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.mypy_cache/
|
|
17
|
+
.ruff_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
htmlcov/
|
|
20
|
+
|
|
21
|
+
# Local agent tooling state (never ship or commit)
|
|
22
|
+
.atl/
|
|
23
|
+
.codegraph/
|
|
24
|
+
.hermes/
|
|
25
|
+
|
|
26
|
+
# Environment files — keep the committed template, never the real one
|
|
27
|
+
.env
|
|
28
|
+
.env.*
|
|
29
|
+
!.env.example
|
|
30
|
+
|
|
31
|
+
# OS noise
|
|
32
|
+
.DS_Store
|
|
33
|
+
Thumbs.db
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to RAGFence are documented here. This project follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) conventions.
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-08-21
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Production evaluation path: declarative control matrix (8 required controls),
|
|
10
|
+
fail-closed `EvaluationGate` with PASS / FAIL / INCONCLUSIVE / SKIPPED statuses,
|
|
11
|
+
and security / utility / overall scores.
|
|
12
|
+
- ReferenceAdapter backed by PostgreSQL 16 + pgvector with DB-resolved identities:
|
|
13
|
+
Acme + Globex tenants, tenant isolation enforced before vector search,
|
|
14
|
+
soft-delete and clearance blocking, MUST_ALLOW / MUST_BLOCK semantics.
|
|
15
|
+
- Identity strategies for `generic_http`: header templates with allowlisted actor
|
|
16
|
+
placeholders and bearer-token resolution from environment configuration.
|
|
17
|
+
- Secret redaction across reports, findings, reasons, and errors.
|
|
18
|
+
- Self-contained wheel: `ragfence init --up` bootstraps the bundled pgvector
|
|
19
|
+
reference environment without a repository checkout.
|
|
20
|
+
- Idempotent bootstrap: a reachable reference database is migrated and reseeded
|
|
21
|
+
in place without invoking Docker Compose.
|
|
22
|
+
- Reusable GitHub Actions evaluation workflow with mandatory pgvector service,
|
|
23
|
+
healthchecks, real Alembic migrations, seeded data, and JSON report artifacts.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Reports with a `.json` destination are always machine-parseable, with or
|
|
28
|
+
without `--json`.
|
|
29
|
+
- Explicit `--config` paths that do not exist fail closed with an actionable
|
|
30
|
+
error instead of silently falling back to defaults.
|
|
31
|
+
- Unwritable report destinations fail closed with exit code 2 and an actionable
|
|
32
|
+
message.
|
|
33
|
+
|
|
34
|
+
### Security
|
|
35
|
+
|
|
36
|
+
- Least-privilege permissions on both CI workflows.
|
|
37
|
+
- Dependency audit clean (`pip-audit`); no secrets in package artifacts;
|
|
38
|
+
sdist excludes local agent tooling state.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
RAGFence is committed to a welcoming, respectful, and harassment-free community for everyone, regardless of identity, background, experience, or viewpoint.
|
|
4
|
+
|
|
5
|
+
## Expected behavior
|
|
6
|
+
|
|
7
|
+
- Be kind, constructive, and respectful.
|
|
8
|
+
- Assume good intent while addressing impact.
|
|
9
|
+
- Focus feedback on the work, not the person.
|
|
10
|
+
- Respect privacy and do not publish private information.
|
|
11
|
+
|
|
12
|
+
## Unacceptable behavior
|
|
13
|
+
|
|
14
|
+
Harassment, discrimination, threats, sexualized conduct, personal attacks, doxxing, and disruptive or abusive behavior are not tolerated.
|
|
15
|
+
|
|
16
|
+
## Reporting
|
|
17
|
+
|
|
18
|
+
Report a concern privately to the project maintainers through the repository's issue/contact channel. Do not include sensitive information in a public issue. Reports will be reviewed promptly and handled confidentially where possible.
|
|
19
|
+
|
|
20
|
+
Maintainers may remove content, restrict participation, or take other action they consider appropriate. Retaliation against anyone who reports a concern in good faith is not acceptable.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Contributing to RAGFence
|
|
2
|
+
|
|
3
|
+
Thanks for contributing. This project follows a spec-driven development (SDD)
|
|
4
|
+
workflow: significant changes start from a proposal in `openspec/changes/` and
|
|
5
|
+
flow through spec, design, tasks, implementation, and verification.
|
|
6
|
+
|
|
7
|
+
## Development setup
|
|
8
|
+
|
|
9
|
+
Requires Python >= 3.12.
|
|
10
|
+
|
|
11
|
+
```console
|
|
12
|
+
python -m venv .venv
|
|
13
|
+
.venv\Scripts\python -m pip install -e ".[dev]" # Windows
|
|
14
|
+
# source .venv/bin/activate && pip install -e ".[dev]" # POSIX
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quality gates
|
|
18
|
+
|
|
19
|
+
All gates must pass before a change is reviewable:
|
|
20
|
+
|
|
21
|
+
```console
|
|
22
|
+
python -m pytest # tests
|
|
23
|
+
ruff check . # lint
|
|
24
|
+
ruff format --check . # formatting
|
|
25
|
+
mypy # strict type checking
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Tests must pass **without Docker and without API keys**. Database-backed tests are
|
|
29
|
+
marked `@pytest.mark.db` and skip when PostgreSQL is unavailable.
|
|
30
|
+
|
|
31
|
+
## Committing
|
|
32
|
+
|
|
33
|
+
- Use Conventional Commits (`feat:`, `fix:`, `chore:`, `docs:`, `ci:`, ...).
|
|
34
|
+
- Tests ship with the behavior they verify — one work unit per commit.
|
|
35
|
+
- Do not add AI/Co-Authored-By attribution lines.
|
|
36
|
+
- Keep PRs under ~400 changed lines; larger changes are delivered as stacked PRs.
|
|
37
|
+
|
|
38
|
+
## Reporting issues
|
|
39
|
+
|
|
40
|
+
Open an issue with reproduction steps and expected vs. actual behavior.
|