tenantshield 0.7.0b0__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.
- tenantshield-0.7.0b0/.editorconfig +15 -0
- tenantshield-0.7.0b0/.gitattributes +37 -0
- tenantshield-0.7.0b0/.github/ISSUE_TEMPLATE/bug_report.yml +75 -0
- tenantshield-0.7.0b0/.github/ISSUE_TEMPLATE/config.yml +9 -0
- tenantshield-0.7.0b0/.github/ISSUE_TEMPLATE/feature_request.yml +41 -0
- tenantshield-0.7.0b0/.github/ISSUE_TEMPLATE/security_disclosure.md +22 -0
- tenantshield-0.7.0b0/.github/PULL_REQUEST_TEMPLATE.md +30 -0
- tenantshield-0.7.0b0/.github/dependabot.yml +22 -0
- tenantshield-0.7.0b0/.github/workflows/bench.yml +27 -0
- tenantshield-0.7.0b0/.github/workflows/ci.yml +79 -0
- tenantshield-0.7.0b0/.github/workflows/docs.yml +31 -0
- tenantshield-0.7.0b0/.github/workflows/pages-deploy.yml +48 -0
- tenantshield-0.7.0b0/.github/workflows/publish-pypi.yml +60 -0
- tenantshield-0.7.0b0/.github/workflows/publish-testpypi.yml +53 -0
- tenantshield-0.7.0b0/.github/workflows/security.yml +53 -0
- tenantshield-0.7.0b0/.gitignore +60 -0
- tenantshield-0.7.0b0/.pre-commit-config.yaml +50 -0
- tenantshield-0.7.0b0/.python-version +1 -0
- tenantshield-0.7.0b0/CHANGELOG.md +2186 -0
- tenantshield-0.7.0b0/CODE_OF_CONDUCT.md +83 -0
- tenantshield-0.7.0b0/CONTRIBUTING.md +74 -0
- tenantshield-0.7.0b0/LICENSE +201 -0
- tenantshield-0.7.0b0/PKG-INFO +356 -0
- tenantshield-0.7.0b0/README.md +294 -0
- tenantshield-0.7.0b0/SECURITY.md +33 -0
- tenantshield-0.7.0b0/docs/adapters/index.md +73 -0
- tenantshield-0.7.0b0/docs/adr/0001-commit-signing-deferral.md +80 -0
- tenantshield-0.7.0b0/docs/adr/0002-django-6-deferral.md +123 -0
- tenantshield-0.7.0b0/docs/adr/0003-django-4-2-empirical-support.md +136 -0
- tenantshield-0.7.0b0/docs/adr/0004-drf-stubs-empirical-support.md +162 -0
- tenantshield-0.7.0b0/docs/adr/0005-tight-upper-bounds-strategy.md +165 -0
- tenantshield-0.7.0b0/docs/adr/0006-sqlalchemy-2-0-only.md +160 -0
- tenantshield-0.7.0b0/docs/adr/0007-event-based-enforcement.md +216 -0
- tenantshield-0.7.0b0/docs/adr/0008-middleware-lifecycle-design.md +201 -0
- tenantshield-0.7.0b0/docs/adr/0009-async-session-adapter-architecture.md +240 -0
- tenantshield-0.7.0b0/docs/adr/0010-cross-adapter-strategy-unification.md +292 -0
- tenantshield-0.7.0b0/docs/adr/0011-observability-architecture.md +257 -0
- tenantshield-0.7.0b0/docs/adr/0012-audit-dual-pattern.md +257 -0
- tenantshield-0.7.0b0/docs/adr/0013-three-mode-read-write-semantics.md +289 -0
- tenantshield-0.7.0b0/docs/adr/0014-phase-6-retrospective.md +314 -0
- tenantshield-0.7.0b0/docs/api/index.md +24 -0
- tenantshield-0.7.0b0/docs/concepts/adopter-governance.md +99 -0
- tenantshield-0.7.0b0/docs/concepts/cross-adapter-parity.md +173 -0
- tenantshield-0.7.0b0/docs/concepts/index.md +57 -0
- tenantshield-0.7.0b0/docs/concepts/security-posture.md +207 -0
- tenantshield-0.7.0b0/docs/evidence/smoke_2b_middleware_output.md +266 -0
- tenantshield-0.7.0b0/docs/evidence/smoke_2c_premises.md +117 -0
- tenantshield-0.7.0b0/docs/getting-started.md +239 -0
- tenantshield-0.7.0b0/docs/index.md +25 -0
- tenantshield-0.7.0b0/docs/observability/async-middleware-migration.md +80 -0
- tenantshield-0.7.0b0/docs/observability/dual-pattern.md +79 -0
- tenantshield-0.7.0b0/docs/observability/integration/opentelemetry.md +69 -0
- tenantshield-0.7.0b0/docs/observability/integration/prometheus.md +81 -0
- tenantshield-0.7.0b0/docs/observability/production-checklist.md +59 -0
- tenantshield-0.7.0b0/docs/observability/quick-start.md +84 -0
- tenantshield-0.7.0b0/examples/01_django/README.md +227 -0
- tenantshield-0.7.0b0/examples/01_django/example_app/__init__.py +0 -0
- tenantshield-0.7.0b0/examples/01_django/example_app/apps.py +12 -0
- tenantshield-0.7.0b0/examples/01_django/example_app/migrations/__init__.py +0 -0
- tenantshield-0.7.0b0/examples/01_django/example_app/models.py +50 -0
- tenantshield-0.7.0b0/examples/01_django/example_app/serializers.py +47 -0
- tenantshield-0.7.0b0/examples/01_django/example_app/urls.py +23 -0
- tenantshield-0.7.0b0/examples/01_django/example_app/viewsets.py +41 -0
- tenantshield-0.7.0b0/examples/01_django/example_project/__init__.py +1 -0
- tenantshield-0.7.0b0/examples/01_django/example_project/asgi.py +11 -0
- tenantshield-0.7.0b0/examples/01_django/example_project/settings.py +70 -0
- tenantshield-0.7.0b0/examples/01_django/example_project/urls.py +9 -0
- tenantshield-0.7.0b0/examples/01_django/example_project/wsgi.py +11 -0
- tenantshield-0.7.0b0/examples/01_django/manage.py +26 -0
- tenantshield-0.7.0b0/examples/01_django/pyproject.toml +20 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/README.md +52 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/cli/README.md +63 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/cli/cli.py +160 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/cli/conftest.py +15 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/cli/models.py +35 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/cli/pyproject.toml +27 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/cli/seed.py +58 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/cli/tests/__init__.py +0 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/cli/tests/test_cli.py +65 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/fastapi/README.md +106 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/fastapi/app.py +205 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/fastapi/conftest.py +16 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/fastapi/models.py +33 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/fastapi/pyproject.toml +33 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/fastapi/tests/__init__.py +0 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/fastapi/tests/test_app.py +88 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/flask/README.md +57 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/flask/app.py +139 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/flask/conftest.py +15 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/flask/models.py +35 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/flask/pyproject.toml +28 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/flask/tests/__init__.py +0 -0
- tenantshield-0.7.0b0/examples/02_sqlalchemy/flask/tests/test_app.py +72 -0
- tenantshield-0.7.0b0/mkdocs.yml +69 -0
- tenantshield-0.7.0b0/pyproject.toml +193 -0
- tenantshield-0.7.0b0/src/tenantshield/__init__.py +119 -0
- tenantshield-0.7.0b0/src/tenantshield/_types.py +23 -0
- tenantshield-0.7.0b0/src/tenantshield/_version.py +3 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/__init__.py +11 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/__init__.py +33 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/admin.py +58 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/apps.py +31 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/checks.py +180 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/decorators.py +176 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/exceptions.py +47 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/managers.py +429 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/middleware/__init__.py +155 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/middleware/strategies/__init__.py +113 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/middleware/strategies/_request_adapter.py +51 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/middleware/strategies/base.py +53 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/middleware/strategies/callable_.py +84 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/middleware/strategies/header.py +80 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/middleware/strategies/jwt.py +104 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/middleware/strategies/subdomain.py +66 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/migrations.py +94 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/scope.py +56 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/django/signals.py +185 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/drf/__init__.py +25 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/drf/exceptions.py +41 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/drf/mixins.py +101 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/drf/permissions.py +72 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/drf/serializers.py +196 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/sqlalchemy/__init__.py +132 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/sqlalchemy/_request_adapter.py +89 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/sqlalchemy/async_lifecycle.py +269 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/sqlalchemy/decorator.py +153 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/sqlalchemy/events.py +448 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/sqlalchemy/exceptions.py +21 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/sqlalchemy/lifecycle.py +235 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/sqlalchemy/middleware.py +592 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/sqlalchemy/migrations.py +87 -0
- tenantshield-0.7.0b0/src/tenantshield/adapters/sqlalchemy/scopes.py +72 -0
- tenantshield-0.7.0b0/src/tenantshield/audit.py +229 -0
- tenantshield-0.7.0b0/src/tenantshield/context.py +157 -0
- tenantshield-0.7.0b0/src/tenantshield/exceptions.py +237 -0
- tenantshield-0.7.0b0/src/tenantshield/observability/__init__.py +45 -0
- tenantshield-0.7.0b0/src/tenantshield/observability/_emit.py +37 -0
- tenantshield-0.7.0b0/src/tenantshield/observability/config.py +39 -0
- tenantshield-0.7.0b0/src/tenantshield/observability/events.py +39 -0
- tenantshield-0.7.0b0/src/tenantshield/policies.py +243 -0
- tenantshield-0.7.0b0/src/tenantshield/py.typed +0 -0
- tenantshield-0.7.0b0/src/tenantshield/registry.py +193 -0
- tenantshield-0.7.0b0/src/tenantshield/strategies/__init__.py +66 -0
- tenantshield-0.7.0b0/src/tenantshield/strategies/_resolver.py +125 -0
- tenantshield-0.7.0b0/src/tenantshield/strategies/base.py +120 -0
- tenantshield-0.7.0b0/src/tenantshield/strategies/callable_.py +58 -0
- tenantshield-0.7.0b0/src/tenantshield/strategies/header.py +41 -0
- tenantshield-0.7.0b0/src/tenantshield/strategies/host.py +52 -0
- tenantshield-0.7.0b0/src/tenantshield/strategies/jwt.py +110 -0
- tenantshield-0.7.0b0/tests/__init__.py +0 -0
- tenantshield-0.7.0b0/tests/conftest.py +61 -0
- tenantshield-0.7.0b0/tests/integration/__init__.py +0 -0
- tenantshield-0.7.0b0/tests/integration/django/__init__.py +0 -0
- tenantshield-0.7.0b0/tests/integration/django/conftest.py +52 -0
- tenantshield-0.7.0b0/tests/integration/django/settings.py +38 -0
- tenantshield-0.7.0b0/tests/integration/django/test_admin.py +51 -0
- tenantshield-0.7.0b0/tests/integration/django/test_checks.py +55 -0
- tenantshield-0.7.0b0/tests/integration/django/test_cross_tenant_audit.py +280 -0
- tenantshield-0.7.0b0/tests/integration/django/test_decorator.py +58 -0
- tenantshield-0.7.0b0/tests/integration/django/test_drf.py +418 -0
- tenantshield-0.7.0b0/tests/integration/django/test_dx_sugar.py +81 -0
- tenantshield-0.7.0b0/tests/integration/django/test_fk_auto_propagation.py +140 -0
- tenantshield-0.7.0b0/tests/integration/django/test_manager.py +65 -0
- tenantshield-0.7.0b0/tests/integration/django/test_middleware.py +241 -0
- tenantshield-0.7.0b0/tests/integration/django/test_middleware_checks.py +153 -0
- tenantshield-0.7.0b0/tests/integration/django/test_migrations_metadata.py +52 -0
- tenantshield-0.7.0b0/tests/integration/django/test_queryset.py +81 -0
- tenantshield-0.7.0b0/tests/integration/django/test_request_adapter.py +55 -0
- tenantshield-0.7.0b0/tests/integration/django/test_signals.py +73 -0
- tenantshield-0.7.0b0/tests/integration/django/test_signals_bench.py +73 -0
- tenantshield-0.7.0b0/tests/integration/django/test_strategies.py +296 -0
- tenantshield-0.7.0b0/tests/integration/django/test_unsafe_unscoped.py +228 -0
- tenantshield-0.7.0b0/tests/integration/django/testapp/__init__.py +0 -0
- tenantshield-0.7.0b0/tests/integration/django/testapp/apps.py +9 -0
- tenantshield-0.7.0b0/tests/integration/django/testapp/models.py +89 -0
- tenantshield-0.7.0b0/tests/integration/django/testapp/serializers.py +25 -0
- tenantshield-0.7.0b0/tests/integration/django/testapp/urls.py +31 -0
- tenantshield-0.7.0b0/tests/integration/django/testapp/views.py +64 -0
- tenantshield-0.7.0b0/tests/integration/django/testapp/viewsets.py +27 -0
- tenantshield-0.7.0b0/tests/integration/examples/__init__.py +0 -0
- tenantshield-0.7.0b0/tests/integration/examples/test_01_django.py +84 -0
- tenantshield-0.7.0b0/tests/integration/test_cross_adapter_strategies.py +190 -0
- tenantshield-0.7.0b0/tests/integration/test_sqlalchemy_middleware_async_fastapi.py +114 -0
- tenantshield-0.7.0b0/tests/unit/__init__.py +0 -0
- tenantshield-0.7.0b0/tests/unit/test_audit_bench.py +78 -0
- tenantshield-0.7.0b0/tests/unit/test_audit_bus.py +219 -0
- tenantshield-0.7.0b0/tests/unit/test_audit_concurrency.py +115 -0
- tenantshield-0.7.0b0/tests/unit/test_audit_sinks.py +100 -0
- tenantshield-0.7.0b0/tests/unit/test_audit_types.py +75 -0
- tenantshield-0.7.0b0/tests/unit/test_context_async.py +107 -0
- tenantshield-0.7.0b0/tests/unit/test_context_audit_integration.py +101 -0
- tenantshield-0.7.0b0/tests/unit/test_context_bench.py +65 -0
- tenantshield-0.7.0b0/tests/unit/test_context_properties.py +95 -0
- tenantshield-0.7.0b0/tests/unit/test_context_sync.py +93 -0
- tenantshield-0.7.0b0/tests/unit/test_exceptions.py +218 -0
- tenantshield-0.7.0b0/tests/unit/test_observability_audit_dual_dispatch.py +230 -0
- tenantshield-0.7.0b0/tests/unit/test_observability_enforcement_events.py +240 -0
- tenantshield-0.7.0b0/tests/unit/test_observability_middleware_events.py +250 -0
- tenantshield-0.7.0b0/tests/unit/test_observability_module.py +104 -0
- tenantshield-0.7.0b0/tests/unit/test_observability_scope_events.py +167 -0
- tenantshield-0.7.0b0/tests/unit/test_policies.py +262 -0
- tenantshield-0.7.0b0/tests/unit/test_policies_properties.py +135 -0
- tenantshield-0.7.0b0/tests/unit/test_registry_class.py +146 -0
- tenantshield-0.7.0b0/tests/unit/test_registry_concurrency.py +39 -0
- tenantshield-0.7.0b0/tests/unit/test_registry_default.py +115 -0
- tenantshield-0.7.0b0/tests/unit/test_registry_properties.py +49 -0
- tenantshield-0.7.0b0/tests/unit/test_smoke.py +126 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_async_lifecycle.py +231 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_async_mapper_events.py +213 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_async_orm_execute.py +221 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_async_sync_coexistence.py +207 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_bulk_operations.py +190 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_decorator.py +97 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_events.py +350 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_flush_commit_timing.py +179 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_lifecycle.py +263 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_middleware_asgi.py +426 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_middleware_async_asgi.py +283 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_middleware_wsgi.py +250 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_migrations_metadata.py +63 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_nested_transactions.py +276 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_raw_sql.py +181 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_request_adapter.py +105 -0
- tenantshield-0.7.0b0/tests/unit/test_sqlalchemy_tenant_scope_for_model.py +54 -0
- tenantshield-0.7.0b0/tests/unit/test_strategies.py +278 -0
- tenantshield-0.7.0b0/tests/unit/test_types.py +22 -0
- tenantshield-0.7.0b0/uv.lock +1944 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
indent_style = space
|
|
5
|
+
indent_size = 4
|
|
6
|
+
end_of_line = lf
|
|
7
|
+
charset = utf-8
|
|
8
|
+
trim_trailing_whitespace = true
|
|
9
|
+
insert_final_newline = true
|
|
10
|
+
|
|
11
|
+
[*.{yml,yaml,toml,json}]
|
|
12
|
+
indent_size = 2
|
|
13
|
+
|
|
14
|
+
[*.md]
|
|
15
|
+
trim_trailing_whitespace = false
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Normalize line endings: LF in repo, platform-appropriate on checkout
|
|
2
|
+
* text=auto eol=lf
|
|
3
|
+
|
|
4
|
+
# Explicit text files
|
|
5
|
+
*.py text eol=lf
|
|
6
|
+
*.pyi text eol=lf
|
|
7
|
+
*.toml text eol=lf
|
|
8
|
+
*.yaml text eol=lf
|
|
9
|
+
*.yml text eol=lf
|
|
10
|
+
*.json text eol=lf
|
|
11
|
+
*.md text eol=lf
|
|
12
|
+
*.txt text eol=lf
|
|
13
|
+
*.cfg text eol=lf
|
|
14
|
+
*.ini text eol=lf
|
|
15
|
+
*.sh text eol=lf
|
|
16
|
+
*.env text eol=lf
|
|
17
|
+
.gitignore text eol=lf
|
|
18
|
+
.gitattributes text eol=lf
|
|
19
|
+
.editorconfig text eol=lf
|
|
20
|
+
LICENSE text eol=lf
|
|
21
|
+
|
|
22
|
+
# Windows-native scripts keep CRLF
|
|
23
|
+
*.ps1 text eol=crlf
|
|
24
|
+
*.bat text eol=crlf
|
|
25
|
+
*.cmd text eol=crlf
|
|
26
|
+
|
|
27
|
+
# Binary
|
|
28
|
+
*.png binary
|
|
29
|
+
*.jpg binary
|
|
30
|
+
*.jpeg binary
|
|
31
|
+
*.gif binary
|
|
32
|
+
*.ico binary
|
|
33
|
+
*.pdf binary
|
|
34
|
+
*.zip binary
|
|
35
|
+
*.tar.gz binary
|
|
36
|
+
*.whl binary
|
|
37
|
+
*.pyc binary
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report a defect in TenantShield.
|
|
3
|
+
title: "[Bug]: "
|
|
4
|
+
labels: ["bug", "needs-triage"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for taking the time to file a bug report. Before you submit:
|
|
10
|
+
|
|
11
|
+
- Do not include real tenant data, credentials, secrets, or production
|
|
12
|
+
identifiers in this report. Replace anything sensitive with a
|
|
13
|
+
placeholder such as `<TENANT_ID>` or `<API_KEY>`.
|
|
14
|
+
- If you believe this is a security vulnerability, do not file a public
|
|
15
|
+
issue. Follow the procedure in `SECURITY.md` instead.
|
|
16
|
+
|
|
17
|
+
- type: textarea
|
|
18
|
+
id: description
|
|
19
|
+
attributes:
|
|
20
|
+
label: What happened?
|
|
21
|
+
description: A clear, concise description of the bug.
|
|
22
|
+
validations:
|
|
23
|
+
required: true
|
|
24
|
+
|
|
25
|
+
- type: textarea
|
|
26
|
+
id: expected
|
|
27
|
+
attributes:
|
|
28
|
+
label: What did you expect to happen?
|
|
29
|
+
validations:
|
|
30
|
+
required: true
|
|
31
|
+
|
|
32
|
+
- type: textarea
|
|
33
|
+
id: reproduction
|
|
34
|
+
attributes:
|
|
35
|
+
label: Minimal reproduction
|
|
36
|
+
description: Steps or a minimal code snippet that reproduces the issue.
|
|
37
|
+
render: python
|
|
38
|
+
validations:
|
|
39
|
+
required: true
|
|
40
|
+
|
|
41
|
+
- type: input
|
|
42
|
+
id: version
|
|
43
|
+
attributes:
|
|
44
|
+
label: TenantShield version
|
|
45
|
+
placeholder: "0.0.1a0"
|
|
46
|
+
validations:
|
|
47
|
+
required: true
|
|
48
|
+
|
|
49
|
+
- type: dropdown
|
|
50
|
+
id: framework
|
|
51
|
+
attributes:
|
|
52
|
+
label: Framework
|
|
53
|
+
options:
|
|
54
|
+
- Django
|
|
55
|
+
- SQLAlchemy
|
|
56
|
+
- Celery
|
|
57
|
+
- DRF
|
|
58
|
+
- Core / None of the above
|
|
59
|
+
validations:
|
|
60
|
+
required: true
|
|
61
|
+
|
|
62
|
+
- type: input
|
|
63
|
+
id: python_version
|
|
64
|
+
attributes:
|
|
65
|
+
label: Python version
|
|
66
|
+
placeholder: "3.13.0"
|
|
67
|
+
validations:
|
|
68
|
+
required: true
|
|
69
|
+
|
|
70
|
+
- type: textarea
|
|
71
|
+
id: logs
|
|
72
|
+
attributes:
|
|
73
|
+
label: Relevant logs or stack trace
|
|
74
|
+
description: Paste any structured log entries or traceback related to the bug.
|
|
75
|
+
render: text
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
|
|
3
|
+
contact_links:
|
|
4
|
+
- name: Security Vulnerability Disclosure
|
|
5
|
+
url: https://github.com/Jhoelperaltap/tenantshield/blob/main/SECURITY.md
|
|
6
|
+
about: For security issues, please email security@ejsupportit.com privately. Do NOT use public issues.
|
|
7
|
+
- name: Documentation
|
|
8
|
+
url: https://jhoelperaltap.github.io/tenantshield/
|
|
9
|
+
about: Check the official documentation site for guides, ADRs, and API reference.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a new feature or enhancement.
|
|
3
|
+
title: "[Feature]: "
|
|
4
|
+
labels: ["enhancement", "needs-triage"]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: problem
|
|
8
|
+
attributes:
|
|
9
|
+
label: What problem does this solve?
|
|
10
|
+
description: Describe the user-facing problem or limitation this feature addresses.
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
|
|
14
|
+
- type: textarea
|
|
15
|
+
id: proposal
|
|
16
|
+
attributes:
|
|
17
|
+
label: Proposed solution or API sketch
|
|
18
|
+
description: A rough proposal. Code snippets or API shapes welcome.
|
|
19
|
+
validations:
|
|
20
|
+
required: true
|
|
21
|
+
|
|
22
|
+
- type: textarea
|
|
23
|
+
id: alternatives
|
|
24
|
+
attributes:
|
|
25
|
+
label: Alternatives considered
|
|
26
|
+
description: Other approaches you considered and why they were not chosen.
|
|
27
|
+
|
|
28
|
+
- type: dropdown
|
|
29
|
+
id: scope
|
|
30
|
+
attributes:
|
|
31
|
+
label: Scope
|
|
32
|
+
options:
|
|
33
|
+
- Core engine
|
|
34
|
+
- Django adapter
|
|
35
|
+
- SQLAlchemy adapter
|
|
36
|
+
- Celery adapter
|
|
37
|
+
- DRF integration
|
|
38
|
+
- Tooling / CI
|
|
39
|
+
- Documentation
|
|
40
|
+
validations:
|
|
41
|
+
required: true
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Security Vulnerability
|
|
3
|
+
about: For security issues, please DO NOT use GitHub issues
|
|
4
|
+
title: ""
|
|
5
|
+
labels: []
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## ⚠️ STOP — Security issues require private disclosure
|
|
9
|
+
|
|
10
|
+
**Do NOT report security vulnerabilities via public GitHub issues.**
|
|
11
|
+
|
|
12
|
+
Security vulnerabilities should be reported privately to:
|
|
13
|
+
|
|
14
|
+
**security@ejsupportit.com**
|
|
15
|
+
|
|
16
|
+
Please see [SECURITY.md](../SECURITY.md) for our security disclosure policy, including:
|
|
17
|
+
|
|
18
|
+
- What to include in your report
|
|
19
|
+
- Expected response timeline (initial acknowledgement within 72 hours)
|
|
20
|
+
- Coordinated disclosure process
|
|
21
|
+
|
|
22
|
+
If you continue and submit this template publicly, your issue **will be closed and redacted**.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- One paragraph describing what this PR does and why. -->
|
|
4
|
+
|
|
5
|
+
## Type of change
|
|
6
|
+
|
|
7
|
+
- [ ] feat — new feature
|
|
8
|
+
- [ ] fix — bug fix
|
|
9
|
+
- [ ] docs — documentation only
|
|
10
|
+
- [ ] test — adding or correcting tests
|
|
11
|
+
- [ ] refactor — code change that neither fixes a bug nor adds a feature
|
|
12
|
+
- [ ] perf — performance improvement
|
|
13
|
+
- [ ] chore — tooling, config, or maintenance
|
|
14
|
+
- [ ] build — build system or dependencies
|
|
15
|
+
- [ ] ci — continuous integration
|
|
16
|
+
|
|
17
|
+
## Checklist
|
|
18
|
+
|
|
19
|
+
- [ ] Tests added or updated, and passing locally (`uv run pytest`).
|
|
20
|
+
- [ ] Type checks pass (`uv run mypy src/tenantshield` and `uv run pyright src/tenantshield`).
|
|
21
|
+
- [ ] Lint and format pass (`uv run pre-commit run --all-files`).
|
|
22
|
+
- [ ] Coverage has not decreased.
|
|
23
|
+
- [ ] `CHANGELOG.md` updated under `[Unreleased]`.
|
|
24
|
+
- [ ] Documentation updated if applicable.
|
|
25
|
+
- [ ] No `TODO` without an associated issue number.
|
|
26
|
+
- [ ] PR is under 400 lines of net change, or a justification is provided.
|
|
27
|
+
|
|
28
|
+
## Related issues
|
|
29
|
+
|
|
30
|
+
<!-- Closes #N, Refs #N, etc. -->
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "uv"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
open-pull-requests-limit: 5
|
|
8
|
+
commit-message:
|
|
9
|
+
prefix: "build"
|
|
10
|
+
prefix-development: "build"
|
|
11
|
+
include: "scope"
|
|
12
|
+
labels: ["dependencies", "python"]
|
|
13
|
+
|
|
14
|
+
- package-ecosystem: "github-actions"
|
|
15
|
+
directory: "/"
|
|
16
|
+
schedule:
|
|
17
|
+
interval: "weekly"
|
|
18
|
+
open-pull-requests-limit: 5
|
|
19
|
+
commit-message:
|
|
20
|
+
prefix: "ci"
|
|
21
|
+
include: "scope"
|
|
22
|
+
labels: ["dependencies", "github-actions"]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: bench
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
bench:
|
|
14
|
+
name: bench
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v6
|
|
18
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
19
|
+
with:
|
|
20
|
+
enable-cache: true
|
|
21
|
+
cache-dependency-glob: "uv.lock"
|
|
22
|
+
python-version: "3.13"
|
|
23
|
+
- run: uv sync --all-extras --dev
|
|
24
|
+
- name: Run benchmarks (slow markers, strict mode)
|
|
25
|
+
run: uv run pytest -m slow -v --no-cov
|
|
26
|
+
env:
|
|
27
|
+
TENANTSHIELD_BENCH_STRICT: "1"
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
lint:
|
|
18
|
+
name: lint
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v6
|
|
22
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
23
|
+
with:
|
|
24
|
+
enable-cache: true
|
|
25
|
+
cache-dependency-glob: "uv.lock"
|
|
26
|
+
python-version: "3.13"
|
|
27
|
+
- run: uv sync --all-extras --dev
|
|
28
|
+
- run: uv run ruff check .
|
|
29
|
+
- run: uv run ruff format --check .
|
|
30
|
+
|
|
31
|
+
typecheck:
|
|
32
|
+
name: typecheck
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v6
|
|
36
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
37
|
+
with:
|
|
38
|
+
enable-cache: true
|
|
39
|
+
cache-dependency-glob: "uv.lock"
|
|
40
|
+
python-version: "3.13"
|
|
41
|
+
- run: uv sync --all-extras --dev
|
|
42
|
+
- run: uv run mypy src/tenantshield
|
|
43
|
+
- run: uv run pyright src/tenantshield
|
|
44
|
+
|
|
45
|
+
test:
|
|
46
|
+
name: test (py${{ matrix.python-version }}, django${{ matrix.django-version }})
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
strategy:
|
|
49
|
+
fail-fast: false
|
|
50
|
+
matrix:
|
|
51
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
52
|
+
django-version: ["4.2", "5.2", "6.0"]
|
|
53
|
+
exclude:
|
|
54
|
+
# Django 6.0 requires Python >=3.12; py3.11 combination is
|
|
55
|
+
# unsatisfiable.
|
|
56
|
+
- python-version: "3.11"
|
|
57
|
+
django-version: "6.0"
|
|
58
|
+
# Django 4.2 LTS predates Python 3.14; django/template/context.py:39
|
|
59
|
+
# raises AttributeError on Python 3.14's super() / __dict__ semantics.
|
|
60
|
+
# Upstream issue (not TenantShield code; 10/11 matrix cells pass).
|
|
61
|
+
# See ADR-0003: Django 4.2 LTS commitment preserved for py3.11-3.13.
|
|
62
|
+
- python-version: "3.14"
|
|
63
|
+
django-version: "4.2"
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@v6
|
|
66
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
67
|
+
with:
|
|
68
|
+
enable-cache: true
|
|
69
|
+
cache-dependency-glob: "uv.lock"
|
|
70
|
+
python-version: ${{ matrix.python-version }}
|
|
71
|
+
- run: uv sync --all-extras --dev
|
|
72
|
+
- run: uv pip install "django==${{ matrix.django-version }}.*"
|
|
73
|
+
- run: uv run pytest
|
|
74
|
+
- uses: actions/upload-artifact@v7
|
|
75
|
+
if: always()
|
|
76
|
+
with:
|
|
77
|
+
name: coverage-py${{ matrix.python-version }}-django${{ matrix.django-version }}
|
|
78
|
+
path: coverage.xml
|
|
79
|
+
retention-days: 7
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- 'docs/**'
|
|
8
|
+
- 'mkdocs.yml'
|
|
9
|
+
- 'src/tenantshield/**'
|
|
10
|
+
push:
|
|
11
|
+
branches: [main]
|
|
12
|
+
paths:
|
|
13
|
+
- 'docs/**'
|
|
14
|
+
- 'mkdocs.yml'
|
|
15
|
+
- 'src/tenantshield/**'
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
build:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v6
|
|
25
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
26
|
+
with:
|
|
27
|
+
enable-cache: true
|
|
28
|
+
cache-dependency-glob: "uv.lock"
|
|
29
|
+
python-version: "3.13"
|
|
30
|
+
- run: uv sync --all-extras --dev
|
|
31
|
+
- run: uv run mkdocs build --strict
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Deploy MkDocs to GitHub Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- 'docs/**'
|
|
8
|
+
- 'mkdocs.yml'
|
|
9
|
+
- 'README.md'
|
|
10
|
+
- '.github/workflows/pages-deploy.yml'
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
pages: write
|
|
16
|
+
id-token: write
|
|
17
|
+
|
|
18
|
+
concurrency:
|
|
19
|
+
group: pages
|
|
20
|
+
cancel-in-progress: false
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
build:
|
|
24
|
+
name: Build MkDocs site
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v6
|
|
28
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
29
|
+
with:
|
|
30
|
+
enable-cache: true
|
|
31
|
+
cache-dependency-glob: "uv.lock"
|
|
32
|
+
python-version: "3.13"
|
|
33
|
+
- run: uv sync --all-extras --dev
|
|
34
|
+
- run: uv run mkdocs build --strict
|
|
35
|
+
- uses: actions/upload-pages-artifact@v3
|
|
36
|
+
with:
|
|
37
|
+
path: site/
|
|
38
|
+
|
|
39
|
+
deploy:
|
|
40
|
+
name: Deploy to GitHub Pages
|
|
41
|
+
needs: build
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
environment:
|
|
44
|
+
name: github-pages
|
|
45
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
46
|
+
steps:
|
|
47
|
+
- id: deployment
|
|
48
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
# Trusted Publishing via OIDC; no PyPI API token in repository secrets.
|
|
9
|
+
# Setup (one-time, browser):
|
|
10
|
+
# 1. Register a pending publisher at
|
|
11
|
+
# https://pypi.org/manage/account/publishing/ with:
|
|
12
|
+
# - PyPI project name: tenantshield
|
|
13
|
+
# - Owner: Jhoelperaltap
|
|
14
|
+
# - Repository name: tenantshield
|
|
15
|
+
# - Workflow filename: publish-pypi.yml
|
|
16
|
+
# - Environment name: pypi
|
|
17
|
+
# 2. In GitHub repo Settings -> Environments, create environment "pypi".
|
|
18
|
+
# (Optional: add required reviewers if you want a manual gate before
|
|
19
|
+
# every public publish; without reviewers it auto-publishes on tag push.)
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
id-token: write
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
build:
|
|
26
|
+
name: Build distributions
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v6
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 0
|
|
32
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
33
|
+
with:
|
|
34
|
+
enable-cache: true
|
|
35
|
+
cache-dependency-glob: "uv.lock"
|
|
36
|
+
python-version: "3.13"
|
|
37
|
+
- run: uv sync --all-extras --dev
|
|
38
|
+
- run: uv build
|
|
39
|
+
- uses: actions/upload-artifact@v7
|
|
40
|
+
with:
|
|
41
|
+
name: dist-pypi
|
|
42
|
+
path: dist/
|
|
43
|
+
retention-days: 7
|
|
44
|
+
|
|
45
|
+
publish-pypi:
|
|
46
|
+
name: Publish to PyPI
|
|
47
|
+
needs: build
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
environment:
|
|
50
|
+
name: pypi
|
|
51
|
+
url: https://pypi.org/project/tenantshield/
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/download-artifact@v5
|
|
54
|
+
with:
|
|
55
|
+
name: dist-pypi
|
|
56
|
+
path: dist/
|
|
57
|
+
- name: Publish distributions to PyPI
|
|
58
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
59
|
+
with:
|
|
60
|
+
skip-existing: true
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Publish to TestPyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
# Trusted Publishing via OIDC; no PyPI API token in repository secrets.
|
|
9
|
+
# Setup: register a pending publisher at
|
|
10
|
+
# https://test.pypi.org/manage/account/publishing/ with the workflow
|
|
11
|
+
# filename above and repository "Jhoelperaltap/tenantshield".
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
id-token: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
build:
|
|
18
|
+
name: Build distributions
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v6
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0
|
|
24
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
25
|
+
with:
|
|
26
|
+
enable-cache: true
|
|
27
|
+
cache-dependency-glob: "uv.lock"
|
|
28
|
+
python-version: "3.13"
|
|
29
|
+
- run: uv sync --all-extras --dev
|
|
30
|
+
- run: uv build
|
|
31
|
+
- uses: actions/upload-artifact@v7
|
|
32
|
+
with:
|
|
33
|
+
name: dist
|
|
34
|
+
path: dist/
|
|
35
|
+
retention-days: 7
|
|
36
|
+
|
|
37
|
+
publish-testpypi:
|
|
38
|
+
name: Publish to TestPyPI
|
|
39
|
+
needs: build
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
environment:
|
|
42
|
+
name: testpypi
|
|
43
|
+
url: https://test.pypi.org/project/tenantshield/
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/download-artifact@v5
|
|
46
|
+
with:
|
|
47
|
+
name: dist
|
|
48
|
+
path: dist/
|
|
49
|
+
- name: Publish distributions to TestPyPI
|
|
50
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
51
|
+
with:
|
|
52
|
+
repository-url: https://test.pypi.org/legacy/
|
|
53
|
+
skip-existing: true
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: security
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "0 6 * * 1"
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
bandit:
|
|
16
|
+
name: bandit
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v6
|
|
20
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
21
|
+
with:
|
|
22
|
+
enable-cache: true
|
|
23
|
+
cache-dependency-glob: "uv.lock"
|
|
24
|
+
python-version: "3.13"
|
|
25
|
+
- run: uv sync --all-extras --dev
|
|
26
|
+
- run: uv run bandit -c pyproject.toml -r src/
|
|
27
|
+
|
|
28
|
+
pip-audit:
|
|
29
|
+
name: pip-audit
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v6
|
|
33
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
34
|
+
with:
|
|
35
|
+
enable-cache: true
|
|
36
|
+
cache-dependency-glob: "uv.lock"
|
|
37
|
+
python-version: "3.13"
|
|
38
|
+
- run: uv sync --all-extras --dev
|
|
39
|
+
- run: uv run pip-audit
|
|
40
|
+
|
|
41
|
+
codeql:
|
|
42
|
+
name: codeql
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
permissions:
|
|
45
|
+
actions: read
|
|
46
|
+
contents: read
|
|
47
|
+
security-events: write
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v6
|
|
50
|
+
- uses: github/codeql-action/init@v4
|
|
51
|
+
with:
|
|
52
|
+
languages: python
|
|
53
|
+
- uses: github/codeql-action/analyze@v4
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Byte-compiled / cached
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
*.pyo
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
*.egg-info/
|
|
8
|
+
build/
|
|
9
|
+
dist/
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
.env
|
|
15
|
+
.envrc
|
|
16
|
+
|
|
17
|
+
# Tooling caches
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.mypy_cache/
|
|
20
|
+
.ruff_cache/
|
|
21
|
+
.tox/
|
|
22
|
+
.nox/
|
|
23
|
+
.hypothesis/
|
|
24
|
+
|
|
25
|
+
# Coverage
|
|
26
|
+
htmlcov/
|
|
27
|
+
.coverage
|
|
28
|
+
coverage.xml
|
|
29
|
+
*.cover
|
|
30
|
+
|
|
31
|
+
# IDE / OS
|
|
32
|
+
.idea/
|
|
33
|
+
.vscode/
|
|
34
|
+
.DS_Store
|
|
35
|
+
Thumbs.db
|
|
36
|
+
|
|
37
|
+
# Documentation build output
|
|
38
|
+
site/
|
|
39
|
+
|
|
40
|
+
# Agent / local-only artifacts (not part of the project)
|
|
41
|
+
CLAUDE.md
|
|
42
|
+
PHASE_*_KICKOFF.md
|
|
43
|
+
PHASE_*_CLOSURE.md
|
|
44
|
+
TENANTSHIELD_ROADMAP.md
|
|
45
|
+
_scratch_*
|
|
46
|
+
.claude/
|
|
47
|
+
.aider*
|
|
48
|
+
.cursor*
|
|
49
|
+
.continue/
|
|
50
|
+
*.local.md
|
|
51
|
+
|
|
52
|
+
# Django runtime artifacts (for examples/)
|
|
53
|
+
*.sqlite3
|
|
54
|
+
*.sqlite3-journal
|
|
55
|
+
examples/*/staticfiles/
|
|
56
|
+
examples/*/media/
|
|
57
|
+
examples/*/local_settings.py
|
|
58
|
+
|
|
59
|
+
# Examples lockfiles (each example resolves locally; Phase 2 precedent)
|
|
60
|
+
examples/**/uv.lock
|