sahra-shared 0.2.2__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.
Files changed (40) hide show
  1. sahra_shared-0.2.2/.gitignore +104 -0
  2. sahra_shared-0.2.2/LICENSE +21 -0
  3. sahra_shared-0.2.2/PKG-INFO +106 -0
  4. sahra_shared-0.2.2/README.md +82 -0
  5. sahra_shared-0.2.2/pyproject.toml +196 -0
  6. sahra_shared-0.2.2/sahra_shared/__init__.py +0 -0
  7. sahra_shared-0.2.2/sahra_shared/auth/__init__.py +53 -0
  8. sahra_shared-0.2.2/sahra_shared/auth/capabilities.py +299 -0
  9. sahra_shared-0.2.2/sahra_shared/auth/claims.py +90 -0
  10. sahra_shared-0.2.2/sahra_shared/auth/coverage.py +248 -0
  11. sahra_shared-0.2.2/sahra_shared/auth/dependencies.py +153 -0
  12. sahra_shared-0.2.2/sahra_shared/auth/guards.py +211 -0
  13. sahra_shared-0.2.2/sahra_shared/events/__init__.py +5 -0
  14. sahra_shared-0.2.2/sahra_shared/events/connection.py +66 -0
  15. sahra_shared-0.2.2/sahra_shared/events/consumer.py +140 -0
  16. sahra_shared-0.2.2/sahra_shared/events/envelope.py +18 -0
  17. sahra_shared-0.2.2/sahra_shared/events/publisher.py +76 -0
  18. sahra_shared-0.2.2/sahra_shared/events/subjects.py +43 -0
  19. sahra_shared-0.2.2/sahra_shared/http/__init__.py +5 -0
  20. sahra_shared-0.2.2/sahra_shared/http/exceptions.py +101 -0
  21. sahra_shared-0.2.2/sahra_shared/http/health.py +28 -0
  22. sahra_shared-0.2.2/sahra_shared/http/models.py +37 -0
  23. sahra_shared-0.2.2/sahra_shared/privacy/__init__.py +13 -0
  24. sahra_shared-0.2.2/sahra_shared/privacy/policies.py +53 -0
  25. sahra_shared-0.2.2/sahra_shared/privacy/types.py +12 -0
  26. sahra_shared-0.2.2/sahra_shared/telemetry/__init__.py +64 -0
  27. sahra_shared-0.2.2/sahra_shared/telemetry/context.py +46 -0
  28. sahra_shared-0.2.2/sahra_shared/telemetry/http_client.py +50 -0
  29. sahra_shared-0.2.2/sahra_shared/telemetry/http_middleware.py +108 -0
  30. sahra_shared-0.2.2/sahra_shared/telemetry/lifecycle.py +193 -0
  31. sahra_shared-0.2.2/sahra_shared/telemetry/logging.py +123 -0
  32. sahra_shared-0.2.2/sahra_shared/telemetry/metrics.py +54 -0
  33. sahra_shared-0.2.2/sahra_shared/telemetry/otel.py +37 -0
  34. sahra_shared-0.2.2/sahra_shared/tenancy/__init__.py +89 -0
  35. sahra_shared-0.2.2/sahra_shared/tenancy/context.py +137 -0
  36. sahra_shared-0.2.2/sahra_shared/tenancy/rls.py +250 -0
  37. sahra_shared-0.2.2/sahra_shared/tenancy/routing.py +108 -0
  38. sahra_shared-0.2.2/sahra_shared/tenancy/session.py +244 -0
  39. sahra_shared-0.2.2/sahra_shared/tenancy/verify.py +351 -0
  40. sahra_shared-0.2.2/uv.lock +1468 -0
@@ -0,0 +1,104 @@
1
+ # Python Bytecode
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Virtual Environment
7
+ venv/
8
+ .env/
9
+ .venv/
10
+ env/
11
+ ENV/
12
+ *.venv
13
+
14
+ # Development Tools
15
+ .idea/
16
+ .vscode/
17
+ *.swp
18
+ *.swo
19
+ *.swn
20
+ *.swm
21
+
22
+ # Testing and Coverage
23
+ htmlcov/
24
+ .tox/
25
+ .nox/
26
+ *.coverage
27
+ .coverage.*
28
+ .cache/
29
+ pytest_cache/
30
+ tests/__pycache__/
31
+ test-results/
32
+ coverage.xml
33
+ *.cover
34
+
35
+ # Logs and Temporary Files
36
+ *.log
37
+ *.tmp
38
+ *.temp
39
+ *.pid
40
+ *.bak
41
+ *.old
42
+ *.orig
43
+ *.rej
44
+
45
+ # Build Artifacts
46
+ build/
47
+ dist/
48
+ *.egg-info/
49
+ *.egg
50
+ .installed.cfg
51
+ eggs/
52
+ sdist/
53
+ wheels/
54
+ share/python-wheels/
55
+
56
+ # Type Checker Caches
57
+ .mypy_cache/
58
+ .dmypy.json
59
+ dmypy.json
60
+ .pytest_cache/
61
+ .ruff_cache/
62
+ .pyright/
63
+
64
+ # IDE Configurations
65
+ *.iml
66
+ *.sublime-project
67
+ *.sublime-workspace
68
+
69
+ # System Files
70
+ .DS_Store
71
+ Thumbs.db
72
+ desktop.ini
73
+
74
+ # Sensitive Data
75
+ .secret/
76
+ *.key
77
+ *.pem
78
+ .env
79
+ .env.*
80
+ !.env.example
81
+
82
+ tmp/
83
+ temp/
84
+
85
+ # uv (Python package manager)
86
+ .uv/
87
+ # uv.lock is COMMITTED for this repository. It is the shared kernel: its
88
+ # resolved dependency set is part of what a release tag means, and every one
89
+ # of the 18 consumers resolves `sahra-shared` from a git revision of this
90
+ # repo. An ignored lockfile made the release irreproducible, so it is tracked
91
+ # deliberately. Do not re-add it here.
92
+
93
+ # FastAPI / Alembic
94
+ alembic/versions/*.pyc
95
+
96
+ # Docker
97
+ *.env.docker
98
+ .dockerenv
99
+
100
+ # Local agent/tooling state. Agent worktrees must NEVER be committed.
101
+ # Note: the .claude/ rules already tracked in this repo stay tracked — gitignore
102
+ # does not untrack existing files. Use `git add -f` to add a new one on purpose.
103
+ .claude/
104
+ .claude/worktrees/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hycind Santhibhavan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.5
2
+ Name: sahra-shared
3
+ Version: 0.2.2
4
+ Summary: Sahra Trans — shared kernel library
5
+ Project-URL: Homepage, https://github.com/Sahra-Trans/sahra-shared
6
+ Project-URL: Repository, https://github.com/Sahra-Trans/sahra-shared
7
+ Project-URL: Issues, https://github.com/Sahra-Trans/sahra-shared/issues
8
+ Author: Hycind Santhibhavan
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Requires-Python: >=3.13
12
+ Requires-Dist: cryptography>=42.0.0
13
+ Requires-Dist: fastapi>=0.115.0
14
+ Requires-Dist: httpx>=0.27.0
15
+ Requires-Dist: nats-py>=2.7.0
16
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.24.0
17
+ Requires-Dist: opentelemetry-instrumentation-fastapi>=0.45b0
18
+ Requires-Dist: opentelemetry-sdk>=1.24.0
19
+ Requires-Dist: prometheus-client>=0.20.0
20
+ Requires-Dist: pydantic>=2.0.0
21
+ Requires-Dist: pyjwt[crypto]>=2.8.0
22
+ Requires-Dist: sqlalchemy>=2.0.0
23
+ Description-Content-Type: text/markdown
24
+
25
+ # sahra-shared
26
+
27
+ [![PyPI](https://img.shields.io/pypi/v/sahra-shared.svg)](https://pypi.org/project/sahra-shared/)
28
+ [![Python](https://img.shields.io/pypi/pyversions/sahra-shared.svg)](https://pypi.org/project/sahra-shared/)
29
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](#license)
30
+
31
+ **A reusable Python library — the shared kernel for Sahra Trans services.**
32
+
33
+ `sahra-shared` is a *library*, not a service. It has **no HTTP server, no database, no
34
+ port, no container and no entrypoint**. Nothing here starts; you `import` it. It is
35
+ published to PyPI and consumed by the Sahra Trans services as an ordinary dependency.
36
+
37
+ The import namespace is **`sahra_shared`**.
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ uv add sahra-shared
43
+ ```
44
+
45
+ ## Use
46
+
47
+ ```python
48
+ from sahra_shared.auth import Capability, CapabilityGuards
49
+ from sahra_shared.events import NATSPublisher, SahraEvent
50
+ from sahra_shared.http import ProblemDetail, make_health_router
51
+ from sahra_shared.privacy import CountryPrivacyPolicy, PIIEmail
52
+ from sahra_shared.telemetry import AppLogger, setup_otel
53
+ from sahra_shared.tenancy import TenantScope, tenant_transaction
54
+ ```
55
+
56
+ ## What it provides
57
+
58
+ | Sub-package | Surface |
59
+ |---|---|
60
+ | `sahra_shared.auth` | `TokenClaims`, RS256 JWT verification against JWKS, the closed `Capability` vocabulary and deny-by-default `CapabilityGuards` |
61
+ | `sahra_shared.events` | `SahraEvent` (CloudEvents envelope), `NATSPublisher` / consumer helpers |
62
+ | `sahra_shared.http` | `ProblemDetail` (RFC 7807) and `make_health_router` — a router **factory** a service mounts; this library serves nothing itself |
63
+ | `sahra_shared.privacy` | PII types (`PIIEmail`, `PIIPhone`, …) and per-country privacy policies |
64
+ | `sahra_shared.telemetry` | OpenTelemetry setup, structured logging, `call_service` (propagates `traceparent`) |
65
+ | `sahra_shared.tenancy` | `TenantScope`, transaction-bound tenant context, row-level-security helpers |
66
+
67
+ Sub-packages are independent: they do not import one another (only `telemetry` is
68
+ depended upon in common). That boundary is enforced by
69
+ `tests/test_import_boundaries.py`.
70
+
71
+ ## Requirements
72
+
73
+ Python **>= 3.13**.
74
+
75
+ ## Development
76
+
77
+ This repository is **uv-only**. Do not use `pip`, `venv`, Poetry or Twine.
78
+
79
+ ```bash
80
+ uv sync --all-groups # install dev + test dependency groups
81
+ uv run pytest # tests
82
+ uv run ruff check . # lint
83
+ uv run ruff format --check .# format
84
+ uv run ty check # type-check
85
+ uv build # build wheel + sdist
86
+ ```
87
+
88
+ `uv.lock` is committed deliberately: the resolved dependency set is part of what a
89
+ release tag means.
90
+
91
+ ## Documentation
92
+
93
+ Design notes, the tenancy/RLS reference and the logging integration guide live
94
+ in the project repository alongside the source, and are not shipped in the
95
+ distribution.
96
+
97
+ ## Releasing
98
+
99
+ Releases are built and published to PyPI by GitHub Actions using **Trusted
100
+ Publishing (OIDC)**. There is no PyPI API token and no stored publishing
101
+ credential. A `vX.Y.Z` tag builds, gates and publishes; a `vX.Y.Z-rc1` tag runs
102
+ the identical gate and stops before publishing.
103
+
104
+ ## License
105
+
106
+ MIT — see [`LICENSE`](LICENSE).
@@ -0,0 +1,82 @@
1
+ # sahra-shared
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/sahra-shared.svg)](https://pypi.org/project/sahra-shared/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/sahra-shared.svg)](https://pypi.org/project/sahra-shared/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](#license)
6
+
7
+ **A reusable Python library — the shared kernel for Sahra Trans services.**
8
+
9
+ `sahra-shared` is a *library*, not a service. It has **no HTTP server, no database, no
10
+ port, no container and no entrypoint**. Nothing here starts; you `import` it. It is
11
+ published to PyPI and consumed by the Sahra Trans services as an ordinary dependency.
12
+
13
+ The import namespace is **`sahra_shared`**.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ uv add sahra-shared
19
+ ```
20
+
21
+ ## Use
22
+
23
+ ```python
24
+ from sahra_shared.auth import Capability, CapabilityGuards
25
+ from sahra_shared.events import NATSPublisher, SahraEvent
26
+ from sahra_shared.http import ProblemDetail, make_health_router
27
+ from sahra_shared.privacy import CountryPrivacyPolicy, PIIEmail
28
+ from sahra_shared.telemetry import AppLogger, setup_otel
29
+ from sahra_shared.tenancy import TenantScope, tenant_transaction
30
+ ```
31
+
32
+ ## What it provides
33
+
34
+ | Sub-package | Surface |
35
+ |---|---|
36
+ | `sahra_shared.auth` | `TokenClaims`, RS256 JWT verification against JWKS, the closed `Capability` vocabulary and deny-by-default `CapabilityGuards` |
37
+ | `sahra_shared.events` | `SahraEvent` (CloudEvents envelope), `NATSPublisher` / consumer helpers |
38
+ | `sahra_shared.http` | `ProblemDetail` (RFC 7807) and `make_health_router` — a router **factory** a service mounts; this library serves nothing itself |
39
+ | `sahra_shared.privacy` | PII types (`PIIEmail`, `PIIPhone`, …) and per-country privacy policies |
40
+ | `sahra_shared.telemetry` | OpenTelemetry setup, structured logging, `call_service` (propagates `traceparent`) |
41
+ | `sahra_shared.tenancy` | `TenantScope`, transaction-bound tenant context, row-level-security helpers |
42
+
43
+ Sub-packages are independent: they do not import one another (only `telemetry` is
44
+ depended upon in common). That boundary is enforced by
45
+ `tests/test_import_boundaries.py`.
46
+
47
+ ## Requirements
48
+
49
+ Python **>= 3.13**.
50
+
51
+ ## Development
52
+
53
+ This repository is **uv-only**. Do not use `pip`, `venv`, Poetry or Twine.
54
+
55
+ ```bash
56
+ uv sync --all-groups # install dev + test dependency groups
57
+ uv run pytest # tests
58
+ uv run ruff check . # lint
59
+ uv run ruff format --check .# format
60
+ uv run ty check # type-check
61
+ uv build # build wheel + sdist
62
+ ```
63
+
64
+ `uv.lock` is committed deliberately: the resolved dependency set is part of what a
65
+ release tag means.
66
+
67
+ ## Documentation
68
+
69
+ Design notes, the tenancy/RLS reference and the logging integration guide live
70
+ in the project repository alongside the source, and are not shipped in the
71
+ distribution.
72
+
73
+ ## Releasing
74
+
75
+ Releases are built and published to PyPI by GitHub Actions using **Trusted
76
+ Publishing (OIDC)**. There is no PyPI API token and no stored publishing
77
+ credential. A `vX.Y.Z` tag builds, gates and publishes; a `vX.Y.Z-rc1` tag runs
78
+ the identical gate and stops before publishing.
79
+
80
+ ## License
81
+
82
+ MIT — see [`LICENSE`](LICENSE).
@@ -0,0 +1,196 @@
1
+ # ======================================================================
2
+ # PROJECT METADATA
3
+ # ======================================================================
4
+ [project]
5
+ name = "sahra-shared"
6
+ version = "0.2.2"
7
+ description = "Sahra Trans — shared kernel library"
8
+ readme = "README.md"
9
+ requires-python = ">=3.13"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ authors = [{ name = "Hycind Santhibhavan" }]
13
+ dependencies = [
14
+ "fastapi>=0.115.0",
15
+ "pydantic>=2.0.0",
16
+ "nats-py>=2.7.0",
17
+ "PyJWT[crypto]>=2.8.0",
18
+ "opentelemetry-sdk>=1.24.0",
19
+ "opentelemetry-exporter-otlp-proto-grpc>=1.24.0",
20
+ "opentelemetry-instrumentation-fastapi>=0.45b0",
21
+ "prometheus-client>=0.20.0",
22
+ "httpx>=0.27.0",
23
+ "sqlalchemy>=2.0.0",
24
+ # Imported directly by sahra_shared/auth/dependencies.py to reject a JWKS entry that
25
+ # carries private key material. Already present transitively via PyJWT[crypto];
26
+ # declared so the import is not a hidden transitive dependency.
27
+ "cryptography>=42.0.0",
28
+ ]
29
+
30
+
31
+ [project.urls]
32
+ Homepage = "https://github.com/Sahra-Trans/sahra-shared"
33
+ Repository = "https://github.com/Sahra-Trans/sahra-shared"
34
+ Issues = "https://github.com/Sahra-Trans/sahra-shared/issues"
35
+
36
+
37
+ # Dev and test tooling lives in [dependency-groups] only. A duplicate
38
+ # [project.optional-dependencies] dev = [...] block used to shadow it; nothing
39
+ # installed the extra (Makefile and both CI workflows use `uv sync --all-groups`)
40
+ # while deptry read its entries as runtime dependencies and failed the build.
41
+ [dependency-groups]
42
+ dev = ["deptry", "ty", "ruff", "vulture", "bandit>=1.7.9", "pip-audit>=2.7.3", "pyright>=1.1.400"]
43
+ test = ["pytest", "pytest-asyncio", "httpx"]
44
+
45
+ # ======================================================================
46
+ # BUILD SYSTEM
47
+ # ======================================================================
48
+ [build-system]
49
+ requires = ["hatchling"]
50
+ build-backend = "hatchling.build"
51
+
52
+ [tool.hatch.build.targets.wheel]
53
+ packages = ["sahra_shared"]
54
+
55
+ # The default sdist is "everything git tracks". That shipped the internal agent
56
+ # instructions (.clinerules/.cursorrules/.windsurfrules, CLAUDE.md, GEMINI.md,
57
+ # QWEN.md, AGENTS.md), the git hooks and their tamper manifest, the GitHub and
58
+ # GitLab CI configuration -- and, because hatchling does not consult .gitignore
59
+ # for this, an untracked `.env` as well.
60
+ #
61
+ # So this is an ALLOWLIST, not a denylist: a new internal file is excluded by
62
+ # default and has to be named here to ship. A denylist publishes whatever
63
+ # nobody remembered to add to it.
64
+ #
65
+ # `docs/` and `tests/` are deliberately NOT shipped. `docs/migrations/` carries
66
+ # the tenant row-level-security migration and `docs/TENANCY.md` the schema
67
+ # design behind it; the tests reference internal endpoint paths and the scheme
68
+ # that authenticates them. None of it is needed to build, install or verify the
69
+ # library, and this is a public index. They remain in the repository, which is
70
+ # where contributors read them.
71
+ [tool.hatch.build.targets.sdist]
72
+ # Patterns are gitignore-style, so they are root-anchored with a leading "/".
73
+ # A bare "README.md" matches at ANY depth and dragged
74
+ # tests/typecheck_violations/README.md into the sdist.
75
+ include = [
76
+ "/sahra_shared/",
77
+ "/README.md",
78
+ "/LICENSE",
79
+ "/pyproject.toml",
80
+ "/uv.lock",
81
+ ]
82
+
83
+ # ======================================================================
84
+ # TY (Fast Type Checker)
85
+ # ======================================================================
86
+ [tool.ty.src]
87
+ include = ["sahra_shared"]
88
+ exclude = ["tests", ".venv"]
89
+ respect-ignore-files = true
90
+
91
+ [tool.ty.environment]
92
+ python-version = "3.13"
93
+ root = ["."]
94
+
95
+ [tool.ty.analysis]
96
+ allowed-unresolved-imports = []
97
+ replace-imports-with-any = []
98
+ respect-type-ignore-comments = true
99
+
100
+ [tool.ty.rules]
101
+ all = "warn"
102
+
103
+ [tool.ty.terminal]
104
+ output-format = "full"
105
+ error-on-warning = false
106
+
107
+ [[tool.ty.overrides]]
108
+ include = ["tests/**", "**/test_*.py"]
109
+
110
+ [tool.ty.overrides.rules]
111
+ possibly-unresolved-reference = "ignore"
112
+
113
+ # ======================================================================
114
+ # PYRIGHT (Type Checker)
115
+ # ======================================================================
116
+ # The 18 services pin pythonVersion = "3.12" while declaring
117
+ # requires-python = ">=3.13". The shared kernel targets 3.13, matching what it
118
+ # actually declares and what its `requires-python` floor allows.
119
+ [tool.pyright]
120
+ include = ["sahra_shared"]
121
+ exclude = [".venv", "**/__pycache__", "tests/typecheck_violations"]
122
+ pythonVersion = "3.13"
123
+ typeCheckingMode = "strict"
124
+ reportMissingTypeStubs = false
125
+ reportUnknownMemberType = false
126
+ reportUnnecessaryIsInstance = false
127
+ # FastAPI route handlers and exception handlers are registered by their
128
+ # decorator and never referenced by name; strict mode reports every one of them
129
+ # as unused. All current hits are of exactly that shape.
130
+ reportUnusedFunction = false
131
+ # Generic third-party models (nats, SahraEvent[Any]) resolve to partially
132
+ # unknown types at their use sites; the annotations we control are explicit.
133
+ reportUnknownVariableType = false
134
+
135
+ # ======================================================================
136
+ # DEPTRY (Dependency Checker)
137
+ # ======================================================================
138
+ [tool.deptry]
139
+ ignore = []
140
+ known_first_party = ["sahra_shared"]
141
+ exclude = ["tests", "\\.venv", ".claude", "docs"]
142
+
143
+ # ======================================================================
144
+ # VULTURE (Find Dead Code)
145
+ # ======================================================================
146
+ [tool.vulture]
147
+ paths = ["sahra_shared"]
148
+ exclude = ["tests", "venv", ".venv"]
149
+ min_confidence = 95
150
+ sort_by_size = true
151
+
152
+ # ======================================================================
153
+ # PYTEST
154
+ # ======================================================================
155
+ [tool.pytest.ini_options]
156
+ testpaths = ["tests"]
157
+ python_files = ["test_*.py"]
158
+ asyncio_mode = "auto"
159
+
160
+ # ======================================================================
161
+ # RUFF (Fast Linter/Formatter)
162
+ # ======================================================================
163
+ [tool.ruff]
164
+ line-length = 180
165
+ indent-width = 4
166
+ target-version = "py313"
167
+ src = ["sahra_shared"]
168
+ extend-exclude = [".claude", "tests", "venv", ".venv", ".claude"]
169
+
170
+ [tool.ruff.lint]
171
+ select = [
172
+ "E", # pycodestyle errors
173
+ "W", # pycodestyle warnings
174
+ "F", # Pyflakes
175
+ "C90", # McCabe complexity
176
+ "I", # isort
177
+ "B", # flake8-bugbear
178
+ "C4", # flake8-comprehensions
179
+ "T20", # flake8-print
180
+ "S", # flake8-bandit (security warnings)
181
+ "UP", # pyupgrade
182
+ "N", # pep8-naming
183
+ ]
184
+ ignore = [
185
+ "UP006", # Dict vs dict
186
+ "UP007", # List vs list
187
+ "UP018", # Typing.List vs list
188
+ ]
189
+
190
+ [tool.ruff.lint.isort]
191
+ known-first-party = ["sahra_shared"]
192
+
193
+ [tool.ruff.format]
194
+ quote-style = "double"
195
+ indent-style = "space"
196
+ line-ending = "auto"
File without changes
@@ -0,0 +1,53 @@
1
+ from sahra_shared.auth.capabilities import (
2
+ FOREIGN_VOCABULARY,
3
+ ROLE_CAPABILITIES,
4
+ Capability,
5
+ RoleName,
6
+ capabilities_for_roles,
7
+ )
8
+ from sahra_shared.auth.claims import TokenClaims
9
+ from sahra_shared.auth.coverage import (
10
+ RouteDeclaration,
11
+ UndeclaredRouteError,
12
+ assert_capability_coverage,
13
+ describe_routes,
14
+ enforce_capability_coverage,
15
+ )
16
+ from sahra_shared.auth.dependencies import (
17
+ ForeignVocabularyError,
18
+ make_auth_dependency,
19
+ require_role,
20
+ )
21
+ from sahra_shared.auth.guards import (
22
+ CapabilityGuards,
23
+ CapabilityRequirement,
24
+ declared_capabilities,
25
+ internal_endpoint,
26
+ internal_reason,
27
+ public_endpoint,
28
+ public_reason,
29
+ )
30
+
31
+ __all__ = [
32
+ "FOREIGN_VOCABULARY",
33
+ "ROLE_CAPABILITIES",
34
+ "Capability",
35
+ "CapabilityGuards",
36
+ "CapabilityRequirement",
37
+ "ForeignVocabularyError",
38
+ "RoleName",
39
+ "RouteDeclaration",
40
+ "TokenClaims",
41
+ "UndeclaredRouteError",
42
+ "assert_capability_coverage",
43
+ "capabilities_for_roles",
44
+ "declared_capabilities",
45
+ "describe_routes",
46
+ "enforce_capability_coverage",
47
+ "internal_endpoint",
48
+ "internal_reason",
49
+ "make_auth_dependency",
50
+ "public_endpoint",
51
+ "public_reason",
52
+ "require_role",
53
+ ]