driftstack-sdk 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.
@@ -0,0 +1,45 @@
1
+ node_modules/
2
+ dist/
3
+ build/
4
+ coverage/
5
+ .tsbuildinfo
6
+ *.tsbuildinfo
7
+
8
+ # Env
9
+ .env
10
+ .env.*
11
+ !.env.example
12
+
13
+ # Editor
14
+ .vscode/
15
+ .idea/
16
+ *.swp
17
+ .DS_Store
18
+
19
+ # Logs
20
+ *.log
21
+ npm-debug.log*
22
+
23
+ # Test artifacts
24
+ test-results/
25
+ playwright-report/
26
+ playwright/.cache/
27
+
28
+ # Drizzle
29
+ drizzle/.migrations-applied
30
+
31
+ # Python SDK
32
+ .venv/
33
+ __pycache__/
34
+ *.egg-info/
35
+ .pytest_cache/
36
+ .mypy_cache/
37
+ .ruff_cache/
38
+ packages/sdk-python/dist/
39
+ .npmrc
40
+
41
+ # GUI client (Tauri)
42
+ apps/gui-client/dist/
43
+ apps/gui-client/src-tauri/target/
44
+ apps/gui-client/src-tauri/gen/
45
+ # Cargo.lock SHOULD be committed for binaries (Tauri app is a binary).
@@ -0,0 +1,226 @@
1
+ Metadata-Version: 2.4
2
+ Name: driftstack-sdk
3
+ Version: 0.1.0
4
+ Summary: Driftstack Python SDK — stealth iPhone Safari automation. Import as `driftstack`.
5
+ Project-URL: Homepage, https://driftstack.dev
6
+ Project-URL: Repository, https://github.com/driftstackdev/driftstack-api
7
+ Project-URL: Issues, https://github.com/driftstackdev/driftstack-api/issues
8
+ Author: Driftstack
9
+ License: MIT
10
+ Keywords: browser-automation,driftstack,ios,safari,stealth
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: httpx<1.0,>=0.27
26
+ Requires-Dist: pydantic[email]<3.0,>=2.5
27
+ Provides-Extra: dev
28
+ Requires-Dist: datamodel-code-generator[http]>=0.25; extra == 'dev'
29
+ Requires-Dist: mypy>=1.10; extra == 'dev'
30
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
31
+ Requires-Dist: pytest>=8.0; extra == 'dev'
32
+ Requires-Dist: respx>=0.21; extra == 'dev'
33
+ Requires-Dist: ruff>=0.5; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # Driftstack Python SDK
37
+
38
+ Stealth iPhone Safari automation, called from Python. Sync (`Driftstack`) and async (`AsyncDriftstack`) clients in one package, sharing the same typed resources, error hierarchy, and retry policy.
39
+
40
+ > **Status:** alpha. The SDK is built, tested, and wheel-buildable, but **not yet published to PyPI** — gated on entity setup. Until then, install from a local checkout or a tagged commit.
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ pip install driftstack-sdk
46
+ ```
47
+
48
+ The dist name on PyPI is `driftstack-sdk`; the import name is `driftstack`.
49
+
50
+ Requires Python 3.10+.
51
+
52
+ ## Quickstart (sync)
53
+
54
+ ```python
55
+ from driftstack import Driftstack
56
+
57
+ with Driftstack(api_key="ds_live_…") as client:
58
+ session = client.sessions.create({"label": "ci-run"})
59
+ client.sessions.navigate(str(session.id), {"url": "https://example.com/"})
60
+ state = client.sessions.get_state(str(session.id))
61
+ print(state.url, state.title)
62
+ client.sessions.destroy(str(session.id))
63
+ ```
64
+
65
+ ## Quickstart (async)
66
+
67
+ ```python
68
+ import asyncio
69
+ from driftstack import AsyncDriftstack
70
+
71
+ async def main():
72
+ async with AsyncDriftstack(api_key="ds_live_…") as client:
73
+ s = await client.sessions.create()
74
+ await client.sessions.navigate(str(s.id), {"url": "https://example.com/"})
75
+ await client.sessions.destroy(str(s.id))
76
+
77
+ asyncio.run(main())
78
+ ```
79
+
80
+ ## Resources
81
+
82
+ Every public API endpoint is a typed method on a resource accessor:
83
+
84
+ | Accessor | Methods |
85
+ | ----------------- | ------------------------------------------------------------------------------------------ |
86
+ | `client.sessions` | `create`, `list`, `get`, `navigate`, `interact`, `wait`, `get_state`, `capture`, `destroy` |
87
+ | `client.api_keys` | `create`, `list`, `revoke` |
88
+ | `client.usage` | `current_period` |
89
+ | `client.webhooks` | `create`, `list`, `get`, `delete`, `list_deliveries` |
90
+
91
+ Inputs accept either a Pydantic model OR a plain `dict` (both serialize identically on the wire). Outputs are typed Pydantic models — IDEs autocomplete every field.
92
+
93
+ ```python
94
+ # Either of these works:
95
+ from driftstack._generated.models import CreateSessionRequest
96
+ client.sessions.create(CreateSessionRequest(label="ci"))
97
+ client.sessions.create({"label": "ci"})
98
+ ```
99
+
100
+ ## Error handling
101
+
102
+ Every server `application/problem+json` response is mapped to a typed exception. The base class is `DriftstackError`; subclasses cover the documented problem types.
103
+
104
+ ```python
105
+ from driftstack import (
106
+ AuthError,
107
+ ConcurrencyLimitError,
108
+ DriftstackError,
109
+ QuotaExceededError,
110
+ RateLimitError,
111
+ ValidationError,
112
+ )
113
+
114
+ try:
115
+ session = client.sessions.create()
116
+ except AuthError:
117
+ ... # invalid / expired / revoked key
118
+ except ConcurrencyLimitError as e:
119
+ ... # e.current_sessions / e.limit
120
+ except QuotaExceededError as e:
121
+ ... # e.current / e.limit / e.record_type
122
+ except RateLimitError as e:
123
+ time.sleep(e.retry_after_seconds or 1)
124
+ except ValidationError as e:
125
+ ... # e.message has the server's detail
126
+ except DriftstackError as e:
127
+ ... # catch-all for anything else
128
+ ```
129
+
130
+ The full hierarchy lives in `driftstack/errors.py`; the URI → exception mapping is in `PROBLEM_TYPE_TO_ERROR`.
131
+
132
+ ## Retry
133
+
134
+ Default policy: 3 retries with exponential backoff and full jitter. Honours `Retry-After` from rate-limit responses. Customize via `RetryConfig`:
135
+
136
+ ```python
137
+ from driftstack import Driftstack
138
+ from driftstack.retry import RetryConfig
139
+
140
+ client = Driftstack(
141
+ api_key="ds_live_…",
142
+ retry=RetryConfig(max_retries=5, initial_delay_ms=500, max_delay_ms=10_000),
143
+ )
144
+
145
+ # Disable entirely for predictable testing:
146
+ client = Driftstack(api_key="…", retry=RetryConfig(enabled=False))
147
+ ```
148
+
149
+ Retryable errors by default: `TransportError` (network / timeout / parse) + `RateLimitError`. Other typed errors (auth, validation, quota, concurrency) propagate immediately.
150
+
151
+ ## Webhook signature verification
152
+
153
+ Stripe-style HMAC-SHA256 over `<unix_seconds>.<raw_body>`. Constant-time comparison via `hmac.compare_digest`. 5-minute default tolerance.
154
+
155
+ ```python
156
+ from driftstack import verify_webhook_signature
157
+
158
+ @app.post("/driftstack-webhook")
159
+ def receive():
160
+ raw = request.get_data() # framework-specific raw body
161
+ ok = verify_webhook_signature(
162
+ body=raw,
163
+ header=request.headers.get("x-driftstack-signature"),
164
+ secret=os.environ["DRIFTSTACK_WEBHOOK_SECRET"],
165
+ )
166
+ if not ok:
167
+ return ("", 401)
168
+ # ... process event ...
169
+ return ("", 204)
170
+ ```
171
+
172
+ A complete stdlib-only receiver lives in [`examples/webhook_receiver.py`](examples/webhook_receiver.py).
173
+
174
+ ## Examples
175
+
176
+ - [`quickstart.py`](examples/quickstart.py) — minimal create/navigate/capture/destroy.
177
+ - [`error_handling.py`](examples/error_handling.py) — granular catch + custom retry loop.
178
+ - [`webhook_receiver.py`](examples/webhook_receiver.py) — stdlib HTTP receiver with signature verify + dispatch.
179
+ - [`langchain_tool.py`](examples/langchain_tool.py) — LangChain `Tool` adapter for AI-agent QA pipelines.
180
+ - [`pytest_fixture.py`](examples/pytest_fixture.py) — drop-in `mock_driftstack` fixture for customer test suites.
181
+
182
+ ## Configuration
183
+
184
+ ```python
185
+ client = Driftstack(
186
+ api_key="ds_live_…", # required
187
+ base_url="https://api.driftstack.dev", # default; override for self-host or test
188
+ timeout_s=30.0, # per-request timeout
189
+ retry=RetryConfig(...), # see above
190
+ http_client=httpx.Client(...) # advanced: BYO httpx.Client
191
+ )
192
+ ```
193
+
194
+ The async client takes the same arguments; pass `httpx.AsyncClient(...)` instead of `httpx.Client(...)`.
195
+
196
+ ## Development
197
+
198
+ ```bash
199
+ # from packages/sdk-python/
200
+ python3.10 -m venv .venv
201
+ source .venv/bin/activate
202
+ pip install -e '.[dev]'
203
+ pytest
204
+ ruff check . && ruff format --check .
205
+ mypy src
206
+ ```
207
+
208
+ Re-generate Pydantic models from a fresh OpenAPI spec:
209
+
210
+ ```bash
211
+ # from the repo root
212
+ npm run sdk:python:dump-spec # writes packages/sdk-python/openapi.json
213
+ npm run sdk:python:generate # runs datamodel-codegen
214
+ ```
215
+
216
+ Build the wheel:
217
+
218
+ ```bash
219
+ # from packages/sdk-python/
220
+ python -m pip install build
221
+ python -m build # → dist/driftstack-X.Y.Z-py3-none-any.whl + sdist
222
+ ```
223
+
224
+ ## License
225
+
226
+ MIT.
@@ -0,0 +1,191 @@
1
+ # Driftstack Python SDK
2
+
3
+ Stealth iPhone Safari automation, called from Python. Sync (`Driftstack`) and async (`AsyncDriftstack`) clients in one package, sharing the same typed resources, error hierarchy, and retry policy.
4
+
5
+ > **Status:** alpha. The SDK is built, tested, and wheel-buildable, but **not yet published to PyPI** — gated on entity setup. Until then, install from a local checkout or a tagged commit.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install driftstack-sdk
11
+ ```
12
+
13
+ The dist name on PyPI is `driftstack-sdk`; the import name is `driftstack`.
14
+
15
+ Requires Python 3.10+.
16
+
17
+ ## Quickstart (sync)
18
+
19
+ ```python
20
+ from driftstack import Driftstack
21
+
22
+ with Driftstack(api_key="ds_live_…") as client:
23
+ session = client.sessions.create({"label": "ci-run"})
24
+ client.sessions.navigate(str(session.id), {"url": "https://example.com/"})
25
+ state = client.sessions.get_state(str(session.id))
26
+ print(state.url, state.title)
27
+ client.sessions.destroy(str(session.id))
28
+ ```
29
+
30
+ ## Quickstart (async)
31
+
32
+ ```python
33
+ import asyncio
34
+ from driftstack import AsyncDriftstack
35
+
36
+ async def main():
37
+ async with AsyncDriftstack(api_key="ds_live_…") as client:
38
+ s = await client.sessions.create()
39
+ await client.sessions.navigate(str(s.id), {"url": "https://example.com/"})
40
+ await client.sessions.destroy(str(s.id))
41
+
42
+ asyncio.run(main())
43
+ ```
44
+
45
+ ## Resources
46
+
47
+ Every public API endpoint is a typed method on a resource accessor:
48
+
49
+ | Accessor | Methods |
50
+ | ----------------- | ------------------------------------------------------------------------------------------ |
51
+ | `client.sessions` | `create`, `list`, `get`, `navigate`, `interact`, `wait`, `get_state`, `capture`, `destroy` |
52
+ | `client.api_keys` | `create`, `list`, `revoke` |
53
+ | `client.usage` | `current_period` |
54
+ | `client.webhooks` | `create`, `list`, `get`, `delete`, `list_deliveries` |
55
+
56
+ Inputs accept either a Pydantic model OR a plain `dict` (both serialize identically on the wire). Outputs are typed Pydantic models — IDEs autocomplete every field.
57
+
58
+ ```python
59
+ # Either of these works:
60
+ from driftstack._generated.models import CreateSessionRequest
61
+ client.sessions.create(CreateSessionRequest(label="ci"))
62
+ client.sessions.create({"label": "ci"})
63
+ ```
64
+
65
+ ## Error handling
66
+
67
+ Every server `application/problem+json` response is mapped to a typed exception. The base class is `DriftstackError`; subclasses cover the documented problem types.
68
+
69
+ ```python
70
+ from driftstack import (
71
+ AuthError,
72
+ ConcurrencyLimitError,
73
+ DriftstackError,
74
+ QuotaExceededError,
75
+ RateLimitError,
76
+ ValidationError,
77
+ )
78
+
79
+ try:
80
+ session = client.sessions.create()
81
+ except AuthError:
82
+ ... # invalid / expired / revoked key
83
+ except ConcurrencyLimitError as e:
84
+ ... # e.current_sessions / e.limit
85
+ except QuotaExceededError as e:
86
+ ... # e.current / e.limit / e.record_type
87
+ except RateLimitError as e:
88
+ time.sleep(e.retry_after_seconds or 1)
89
+ except ValidationError as e:
90
+ ... # e.message has the server's detail
91
+ except DriftstackError as e:
92
+ ... # catch-all for anything else
93
+ ```
94
+
95
+ The full hierarchy lives in `driftstack/errors.py`; the URI → exception mapping is in `PROBLEM_TYPE_TO_ERROR`.
96
+
97
+ ## Retry
98
+
99
+ Default policy: 3 retries with exponential backoff and full jitter. Honours `Retry-After` from rate-limit responses. Customize via `RetryConfig`:
100
+
101
+ ```python
102
+ from driftstack import Driftstack
103
+ from driftstack.retry import RetryConfig
104
+
105
+ client = Driftstack(
106
+ api_key="ds_live_…",
107
+ retry=RetryConfig(max_retries=5, initial_delay_ms=500, max_delay_ms=10_000),
108
+ )
109
+
110
+ # Disable entirely for predictable testing:
111
+ client = Driftstack(api_key="…", retry=RetryConfig(enabled=False))
112
+ ```
113
+
114
+ Retryable errors by default: `TransportError` (network / timeout / parse) + `RateLimitError`. Other typed errors (auth, validation, quota, concurrency) propagate immediately.
115
+
116
+ ## Webhook signature verification
117
+
118
+ Stripe-style HMAC-SHA256 over `<unix_seconds>.<raw_body>`. Constant-time comparison via `hmac.compare_digest`. 5-minute default tolerance.
119
+
120
+ ```python
121
+ from driftstack import verify_webhook_signature
122
+
123
+ @app.post("/driftstack-webhook")
124
+ def receive():
125
+ raw = request.get_data() # framework-specific raw body
126
+ ok = verify_webhook_signature(
127
+ body=raw,
128
+ header=request.headers.get("x-driftstack-signature"),
129
+ secret=os.environ["DRIFTSTACK_WEBHOOK_SECRET"],
130
+ )
131
+ if not ok:
132
+ return ("", 401)
133
+ # ... process event ...
134
+ return ("", 204)
135
+ ```
136
+
137
+ A complete stdlib-only receiver lives in [`examples/webhook_receiver.py`](examples/webhook_receiver.py).
138
+
139
+ ## Examples
140
+
141
+ - [`quickstart.py`](examples/quickstart.py) — minimal create/navigate/capture/destroy.
142
+ - [`error_handling.py`](examples/error_handling.py) — granular catch + custom retry loop.
143
+ - [`webhook_receiver.py`](examples/webhook_receiver.py) — stdlib HTTP receiver with signature verify + dispatch.
144
+ - [`langchain_tool.py`](examples/langchain_tool.py) — LangChain `Tool` adapter for AI-agent QA pipelines.
145
+ - [`pytest_fixture.py`](examples/pytest_fixture.py) — drop-in `mock_driftstack` fixture for customer test suites.
146
+
147
+ ## Configuration
148
+
149
+ ```python
150
+ client = Driftstack(
151
+ api_key="ds_live_…", # required
152
+ base_url="https://api.driftstack.dev", # default; override for self-host or test
153
+ timeout_s=30.0, # per-request timeout
154
+ retry=RetryConfig(...), # see above
155
+ http_client=httpx.Client(...) # advanced: BYO httpx.Client
156
+ )
157
+ ```
158
+
159
+ The async client takes the same arguments; pass `httpx.AsyncClient(...)` instead of `httpx.Client(...)`.
160
+
161
+ ## Development
162
+
163
+ ```bash
164
+ # from packages/sdk-python/
165
+ python3.10 -m venv .venv
166
+ source .venv/bin/activate
167
+ pip install -e '.[dev]'
168
+ pytest
169
+ ruff check . && ruff format --check .
170
+ mypy src
171
+ ```
172
+
173
+ Re-generate Pydantic models from a fresh OpenAPI spec:
174
+
175
+ ```bash
176
+ # from the repo root
177
+ npm run sdk:python:dump-spec # writes packages/sdk-python/openapi.json
178
+ npm run sdk:python:generate # runs datamodel-codegen
179
+ ```
180
+
181
+ Build the wheel:
182
+
183
+ ```bash
184
+ # from packages/sdk-python/
185
+ python -m pip install build
186
+ python -m build # → dist/driftstack-X.Y.Z-py3-none-any.whl + sdist
187
+ ```
188
+
189
+ ## License
190
+
191
+ MIT.
@@ -0,0 +1,112 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.21"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "driftstack-sdk"
7
+ version = "0.1.0"
8
+ description = "Driftstack Python SDK — stealth iPhone Safari automation. Import as `driftstack`."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "Driftstack" }
14
+ ]
15
+ keywords = ["driftstack", "browser-automation", "ios", "safari", "stealth"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3 :: Only",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Programming Language :: Python :: 3.14",
28
+ "Topic :: Software Development :: Libraries :: Python Modules",
29
+ "Typing :: Typed",
30
+ ]
31
+ dependencies = [
32
+ "httpx>=0.27,<1.0",
33
+ "pydantic[email]>=2.5,<3.0",
34
+ ]
35
+
36
+ [project.optional-dependencies]
37
+ dev = [
38
+ "pytest>=8.0",
39
+ "pytest-asyncio>=0.23",
40
+ "respx>=0.21",
41
+ "ruff>=0.5",
42
+ "mypy>=1.10",
43
+ "datamodel-code-generator[http]>=0.25",
44
+ ]
45
+
46
+ [project.urls]
47
+ Homepage = "https://driftstack.dev"
48
+ Repository = "https://github.com/driftstackdev/driftstack-api"
49
+ Issues = "https://github.com/driftstackdev/driftstack-api/issues"
50
+
51
+ [tool.hatch.build.targets.wheel]
52
+ packages = ["src/driftstack"]
53
+
54
+ [tool.hatch.build.targets.sdist]
55
+ include = [
56
+ "/src/driftstack",
57
+ "/README.md",
58
+ "/pyproject.toml",
59
+ ]
60
+
61
+ # ──────────────────────────────────────────────────────────────────
62
+ # pytest
63
+ # ──────────────────────────────────────────────────────────────────
64
+
65
+ [tool.pytest.ini_options]
66
+ testpaths = ["tests"]
67
+ asyncio_mode = "auto"
68
+ filterwarnings = [
69
+ "error",
70
+ # Pydantic emits deprecation warnings for some patterns we generate
71
+ # via datamodel-code-generator; tolerate them so tests don't fail on
72
+ # codegen output we don't fully control.
73
+ "default::DeprecationWarning:pydantic",
74
+ "default::DeprecationWarning:driftstack._generated",
75
+ ]
76
+
77
+ # ──────────────────────────────────────────────────────────────────
78
+ # ruff
79
+ # ──────────────────────────────────────────────────────────────────
80
+
81
+ [tool.ruff]
82
+ line-length = 100
83
+ target-version = "py310"
84
+ extend-exclude = ["src/driftstack/_generated"]
85
+
86
+ [tool.ruff.lint]
87
+ # Conservative starter set; tighten in follow-up commits.
88
+ select = ["E", "F", "I", "B", "UP", "PT"]
89
+ ignore = []
90
+
91
+ [tool.ruff.lint.per-file-ignores]
92
+ "tests/**" = ["B", "PT011"]
93
+
94
+ # ──────────────────────────────────────────────────────────────────
95
+ # mypy — strict on hand-written code; permissive on _generated
96
+ # ──────────────────────────────────────────────────────────────────
97
+
98
+ [tool.mypy]
99
+ python_version = "3.10"
100
+ strict = true
101
+ warn_unused_configs = true
102
+ exclude = ["build/", "dist/"]
103
+
104
+ [[tool.mypy.overrides]]
105
+ module = "driftstack._generated.*"
106
+ # Codegen output isn't always strict-clean — `conint(...)` /
107
+ # `constr(...)` factory calls aren't valid type annotations to mypy
108
+ # even though Pydantic v2 accepts them at runtime. Skip type-checking
109
+ # for the codegen module entirely; the wrapper layer that customers
110
+ # actually touch stays strict, and the generated models are runtime-
111
+ # tested via tests/test_generated_models.py.
112
+ ignore_errors = true
@@ -0,0 +1,60 @@
1
+ """Driftstack Python SDK.
2
+
3
+ Customer-facing entry points re-exported here so callers can write::
4
+
5
+ from driftstack import Driftstack, AsyncDriftstack, DriftstackError
6
+
7
+ Resource accessors live on the client instance::
8
+
9
+ client = Driftstack(api_key="ds_live_...")
10
+ session = client.sessions.create()
11
+ client.sessions.navigate(session.id, url="https://example.com")
12
+ client.sessions.destroy(session.id)
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from driftstack._version import __version__
18
+ from driftstack.client import AsyncDriftstack, Driftstack
19
+ from driftstack.errors import (
20
+ AuthError,
21
+ ConcurrencyLimitError,
22
+ ConflictError,
23
+ DriftstackError,
24
+ DriverError,
25
+ ExpiredKeyError,
26
+ ForbiddenError,
27
+ InvalidKeyError,
28
+ NotFoundError,
29
+ QuotaExceededError,
30
+ RateLimitError,
31
+ RevokedKeyError,
32
+ SessionDestroyedError,
33
+ SessionNotFoundError,
34
+ TransportError,
35
+ ValidationError,
36
+ )
37
+ from driftstack.webhook_signature import verify_webhook_signature
38
+
39
+ __all__ = [
40
+ "__version__",
41
+ "Driftstack",
42
+ "AsyncDriftstack",
43
+ "DriftstackError",
44
+ "AuthError",
45
+ "ForbiddenError",
46
+ "InvalidKeyError",
47
+ "ExpiredKeyError",
48
+ "RevokedKeyError",
49
+ "ConflictError",
50
+ "NotFoundError",
51
+ "RateLimitError",
52
+ "QuotaExceededError",
53
+ "ConcurrencyLimitError",
54
+ "SessionNotFoundError",
55
+ "SessionDestroyedError",
56
+ "DriverError",
57
+ "ValidationError",
58
+ "TransportError",
59
+ "verify_webhook_signature",
60
+ ]
@@ -0,0 +1,6 @@
1
+ """Codegen output. Regenerated by ``scripts/generate.sh``.
2
+
3
+ Hand-edit nothing in this package — it gets clobbered every regeneration.
4
+ Customer-facing types are re-exported from :mod:`driftstack` (the package
5
+ root); to add a wrapping layer, edit there.
6
+ """