isa-sdk 1.0.0__py3-none-any.whl

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 (100) hide show
  1. isa_sdk/__init__.py +60 -0
  2. isa_sdk/account.py +5 -0
  3. isa_sdk/catalog.py +5 -0
  4. isa_sdk/core.py +5 -0
  5. isa_sdk/proxy.py +5 -0
  6. isa_sdk/py.typed +0 -0
  7. isa_sdk/rapidsign.py +5 -0
  8. isa_sdk/webhooks.py +5 -0
  9. isa_sdk/zyins.py +50 -0
  10. isa_sdk-1.0.0.dist-info/METADATA +328 -0
  11. isa_sdk-1.0.0.dist-info/RECORD +100 -0
  12. isa_sdk-1.0.0.dist-info/WHEEL +4 -0
  13. sah_sdk/__contract__.py +257 -0
  14. sah_sdk/__init__.py +133 -0
  15. sah_sdk/_codemod/__init__.py +25 -0
  16. sah_sdk/_codemod/__main__.py +45 -0
  17. sah_sdk/_codemod/rewriter.py +179 -0
  18. sah_sdk/account/__init__.py +142 -0
  19. sah_sdk/account/_op.py +86 -0
  20. sah_sdk/account/branding.py +107 -0
  21. sah_sdk/account/cases.py +173 -0
  22. sah_sdk/account/email.py +92 -0
  23. sah_sdk/account/preferences.py +102 -0
  24. sah_sdk/account/reference_data.py +111 -0
  25. sah_sdk/catalog/__init__.py +36 -0
  26. sah_sdk/catalog/carriers.py +107 -0
  27. sah_sdk/catalog/conditions.py +44 -0
  28. sah_sdk/catalog/errors.py +89 -0
  29. sah_sdk/catalog/medications.py +1909 -0
  30. sah_sdk/catalog/products.py +312 -0
  31. sah_sdk/catalog/scopes.py +35 -0
  32. sah_sdk/catalog/sign_events.py +24 -0
  33. sah_sdk/catalog/states.py +236 -0
  34. sah_sdk/core/__init__.py +56 -0
  35. sah_sdk/core/auth.py +95 -0
  36. sah_sdk/core/bootstrap.py +135 -0
  37. sah_sdk/core/constants.py +117 -0
  38. sah_sdk/core/credential_store.py +96 -0
  39. sah_sdk/core/debug.py +157 -0
  40. sah_sdk/core/env.py +73 -0
  41. sah_sdk/core/envelope.py +93 -0
  42. sah_sdk/core/errors.py +388 -0
  43. sah_sdk/core/idempotency.py +16 -0
  44. sah_sdk/core/json_response.py +40 -0
  45. sah_sdk/core/license_hmac.py +134 -0
  46. sah_sdk/core/session.py +336 -0
  47. sah_sdk/core/sign_request.py +133 -0
  48. sah_sdk/core/transport.py +102 -0
  49. sah_sdk/core/value_types.py +96 -0
  50. sah_sdk/core/wire.py +70 -0
  51. sah_sdk/isa.py +1635 -0
  52. sah_sdk/proxy/__init__.py +88 -0
  53. sah_sdk/proxy/call.py +302 -0
  54. sah_sdk/py.typed +0 -0
  55. sah_sdk/rapidsign/__init__.py +30 -0
  56. sah_sdk/webhooks.py +29 -0
  57. sah_sdk/zyins/__init__.py +210 -0
  58. sah_sdk/zyins/account_namespaces.py +162 -0
  59. sah_sdk/zyins/applicant.py +180 -0
  60. sah_sdk/zyins/branding.py +75 -0
  61. sah_sdk/zyins/bundled_api_versions.py +72 -0
  62. sah_sdk/zyins/cases/__init__.py +254 -0
  63. sah_sdk/zyins/cases/storage.py +104 -0
  64. sah_sdk/zyins/cases/zero_knowledge.py +269 -0
  65. sah_sdk/zyins/cases.py +141 -0
  66. sah_sdk/zyins/cases_storage.py +19 -0
  67. sah_sdk/zyins/client.py +431 -0
  68. sah_sdk/zyins/coverage.py +111 -0
  69. sah_sdk/zyins/credential_state.py +151 -0
  70. sah_sdk/zyins/datasets.py +35 -0
  71. sah_sdk/zyins/datasets_v3.py +764 -0
  72. sah_sdk/zyins/health.py +47 -0
  73. sah_sdk/zyins/isa_options.py +335 -0
  74. sah_sdk/zyins/license.py +46 -0
  75. sah_sdk/zyins/licenses.py +122 -0
  76. sah_sdk/zyins/licenses_facade.py +227 -0
  77. sah_sdk/zyins/logos.py +147 -0
  78. sah_sdk/zyins/measurements.py +279 -0
  79. sah_sdk/zyins/plan_info_label.py +128 -0
  80. sah_sdk/zyins/preferences.py +74 -0
  81. sah_sdk/zyins/prequalify.py +282 -0
  82. sah_sdk/zyins/prequalify_legacy_blob.py +44 -0
  83. sah_sdk/zyins/prequalify_v3.py +904 -0
  84. sah_sdk/zyins/product.py +216 -0
  85. sah_sdk/zyins/products.py +54 -0
  86. sah_sdk/zyins/quote.py +80 -0
  87. sah_sdk/zyins/quote_v3.py +153 -0
  88. sah_sdk/zyins/reference/__init__.py +435 -0
  89. sah_sdk/zyins/reference/_make_key.py +39 -0
  90. sah_sdk/zyins/reference/autocomplete_algorithm.py +406 -0
  91. sah_sdk/zyins/reference/autocorrector.py +325 -0
  92. sah_sdk/zyins/reference/concept.py +173 -0
  93. sah_sdk/zyins/reference/index.py +260 -0
  94. sah_sdk/zyins/reference/match_algorithm.py +111 -0
  95. sah_sdk/zyins/reference/reference_index.py +215 -0
  96. sah_sdk/zyins/reference/sort.py +31 -0
  97. sah_sdk/zyins/reference/suggestion.py +77 -0
  98. sah_sdk/zyins/reference_data.py +42 -0
  99. sah_sdk/zyins/reference_v3.py +394 -0
  100. sah_sdk/zyins/usage.py +32 -0
isa_sdk/__init__.py ADDED
@@ -0,0 +1,60 @@
1
+ """``isa_sdk`` — cross-language naming alias for :mod:`sah_sdk`.
2
+
3
+ The TypeScript SDK ships as ``@isa-sdk/sdk``; the canonical Python
4
+ import path going forward is ``isa_sdk``. To avoid a hard rename break
5
+ during the transition, this package re-exports the entire ``sah_sdk``
6
+ public surface verbatim. Either spelling resolves to the same objects:
7
+
8
+ >>> import sah_sdk, isa_sdk
9
+ >>> isa_sdk.Isa is sah_sdk.Isa
10
+ True
11
+
12
+ Submodules (``isa_sdk.zyins``, ``isa_sdk.core``, …) resolve to the
13
+ corresponding ``sah_sdk`` modules, so ``from isa_sdk.zyins import
14
+ Applicant`` resolves natively under both runtime and mypy.
15
+
16
+ The legacy ``sah_sdk`` import path remains supported for one minor
17
+ release; new code should prefer ``isa_sdk``. Sunset target: v0.7.0.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import importlib
23
+ import pkgutil
24
+ import sys
25
+
26
+ from sah_sdk import * # noqa: F403 (re-export public surface)
27
+ from sah_sdk import __all__ as _sah_all
28
+ from sah_sdk import __version__
29
+
30
+ _SUBMODULE_ALIASES = (
31
+ "account",
32
+ "catalog",
33
+ "core",
34
+ "proxy",
35
+ "rapidsign",
36
+ "webhooks",
37
+ "zyins",
38
+ )
39
+
40
+
41
+ def _install_aliases() -> None:
42
+ for name in _SUBMODULE_ALIASES:
43
+ source = importlib.import_module(f"sah_sdk.{name}")
44
+ target_name = f"{__name__}.{name}"
45
+ sys.modules[target_name] = source
46
+ setattr(sys.modules[__name__], name, source)
47
+
48
+ source_path = getattr(source, "__path__", None)
49
+ if source_path is None:
50
+ continue
51
+
52
+ for module_info in pkgutil.walk_packages(source_path, f"sah_sdk.{name}."):
53
+ child = importlib.import_module(module_info.name)
54
+ child_target = f"{__name__}.{module_info.name.removeprefix('sah_sdk.')}"
55
+ sys.modules[child_target] = child
56
+
57
+
58
+ _install_aliases()
59
+
60
+ __all__ = [*_sah_all, "__version__"]
isa_sdk/account.py ADDED
@@ -0,0 +1,5 @@
1
+ """``isa_sdk.account`` — alias for :mod:`sah_sdk.account`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from sah_sdk.account import * # noqa: F403
isa_sdk/catalog.py ADDED
@@ -0,0 +1,5 @@
1
+ """``isa_sdk.catalog`` — alias for :mod:`sah_sdk.catalog`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from sah_sdk.catalog import * # noqa: F403
isa_sdk/core.py ADDED
@@ -0,0 +1,5 @@
1
+ """``isa_sdk.core`` — alias for :mod:`sah_sdk.core`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from sah_sdk.core import * # noqa: F403
isa_sdk/proxy.py ADDED
@@ -0,0 +1,5 @@
1
+ """``isa_sdk.proxy`` — alias for :mod:`sah_sdk.proxy`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from sah_sdk.proxy import * # noqa: F403
isa_sdk/py.typed ADDED
File without changes
isa_sdk/rapidsign.py ADDED
@@ -0,0 +1,5 @@
1
+ """``isa_sdk.rapidsign`` — alias for :mod:`sah_sdk.rapidsign`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from sah_sdk.rapidsign import * # noqa: F403
isa_sdk/webhooks.py ADDED
@@ -0,0 +1,5 @@
1
+ """``isa_sdk.webhooks`` — alias for :mod:`sah_sdk.webhooks`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from sah_sdk.webhooks import * # noqa: F403
isa_sdk/zyins.py ADDED
@@ -0,0 +1,50 @@
1
+ """``isa_sdk.zyins`` — alias for :mod:`sah_sdk.zyins`.
2
+
3
+ Importing here is identical to importing from ``sah_sdk.zyins``; both
4
+ spellings yield the same module object via the parent package's
5
+ ``sys.modules`` binding (see :mod:`isa_sdk`).
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from sah_sdk.zyins import * # noqa: F403
11
+ from sah_sdk.zyins import ( # noqa: F401
12
+ Applicant,
13
+ Carrier,
14
+ Condition,
15
+ Coverage,
16
+ CoverageType,
17
+ Eligibility,
18
+ Envelope,
19
+ Height,
20
+ HeightParseError,
21
+ IsaApiError,
22
+ IsaConfigError,
23
+ IsaIdempotencyConflictError,
24
+ IsaRateLimitError,
25
+ Medication,
26
+ NicotineDuration,
27
+ NicotineProductUsage,
28
+ NicotineUsage,
29
+ NicotineUsageInput,
30
+ PlanProduct,
31
+ Premium,
32
+ PrequalifyError,
33
+ PrequalifyInput,
34
+ PrequalifyPlan,
35
+ PrequalifyResult,
36
+ Product,
37
+ ProductCatalog,
38
+ ProductSelection,
39
+ ProductType,
40
+ QuoteInput,
41
+ QuoteResult,
42
+ QuoteType,
43
+ RateLimitError,
44
+ RawResponse,
45
+ Sex,
46
+ Weight,
47
+ WeightParseError,
48
+ ZyInsClient,
49
+ ZyInsError,
50
+ )
@@ -0,0 +1,328 @@
1
+ Metadata-Version: 2.4
2
+ Name: isa-sdk
3
+ Version: 1.0.0
4
+ Summary: Unified Python SDK for ISA APIs (zyins, rapidsign, proxy).
5
+ Project-URL: Homepage, https://github.com/Software-Automation-Holdings-LLC/isa-platform
6
+ Project-URL: Source, https://github.com/Software-Automation-Holdings-LLC/isa-platform
7
+ Author: Software Automation Holdings, LLC
8
+ License: Apache-2.0
9
+ Keywords: insurance,isa,rapidsign,sdk,zyins
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: cryptography>=42
22
+ Requires-Dist: httpx>=0.27
23
+ Requires-Dist: libcst>=1.4
24
+ Requires-Dist: pydantic>=2.6
25
+ Provides-Extra: dev
26
+ Requires-Dist: build>=1.2; extra == 'dev'
27
+ Requires-Dist: libcst>=1.4; extra == 'dev'
28
+ Requires-Dist: mypy>=1.10; extra == 'dev'
29
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
30
+ Requires-Dist: pytest>=8.0; extra == 'dev'
31
+ Requires-Dist: respx>=0.21; extra == 'dev'
32
+ Requires-Dist: ruff>=0.5; extra == 'dev'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # sah-sdk
36
+
37
+ Python SDK for the [Best Plan Pro API](https://docs.isaapi.com) — powered by the ZyINS engine. Mirrors the
38
+ canonical TypeScript SDK at `packages/zyins/js/` with Python-idiomatic
39
+ naming (`snake_case`) and pydantic v2 models.
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ pip install sah-sdk
45
+ ```
46
+
47
+ > **GitHub Packages fallback.** Until `sah-sdk` is fully published on PyPI, install directly from the source repository:
48
+ >
49
+ > ```bash
50
+ > pip install "git+https://github.com/Software-Automation-Holdings-LLC/sdk.git@sdk/v0.5.0#subdirectory=packages/python"
51
+ > ```
52
+ >
53
+ > The wire surface is identical either way; only the install command changes.
54
+
55
+ ## Quick start
56
+
57
+ ```python
58
+ import os
59
+ from sah_sdk.zyins import Isa, Applicant, Coverage, PrequalifyInput, Sex
60
+
61
+ # Reads ISA_TOKEN from the environment — no explicit token needed.
62
+ isa = Isa.with_bearer()
63
+
64
+ result = isa.zyins.prequalify(PrequalifyInput(
65
+ applicant=Applicant(
66
+ dob="1962-04-18",
67
+ sex=Sex.MALE,
68
+ height_inches=70,
69
+ weight_pounds=195,
70
+ state="NC",
71
+ nicotine_use="none",
72
+ ),
73
+ coverage=Coverage.face_value(100_000),
74
+ products="colonial-penn.final-expense",
75
+ ))
76
+
77
+ for plan in result.data.plans:
78
+ print(plan.brand, plan.tier, plan.monthly_premium)
79
+ ```
80
+
81
+ `Isa.with_bearer()` reads `ISA_TOKEN` from the environment. `Authorization: Bearer <token>`,
82
+ `Idempotency-Key`, and the date-pinned `Version` header are set automatically.
83
+
84
+ ## First call in <15 lines
85
+
86
+ ```python
87
+ from sah_sdk.zyins import Isa, Coverage
88
+
89
+ isa = Isa.with_keycode(
90
+ keycode="SDV-HWH-WDD",
91
+ email="john.doe@acme-agency.com",
92
+ )
93
+ result = isa.zyins.prequalify_v2(
94
+ applicant={"dob": "1962-04-18", "sex": "male", "state": "NC"},
95
+ coverage=Coverage.face_value(25_000),
96
+ products="colonial-penn.final-expense",
97
+ )
98
+ print(result.data.plans[0].monthly_premium)
99
+ ```
100
+
101
+ ## Per-surface API versions
102
+
103
+ The ISA API is a federation of independently versioned surfaces. Every SDK
104
+ release exports a frozen `BUNDLED_API_VERSIONS` mapping recording which
105
+ `/vN` each surface targets:
106
+
107
+ ```python
108
+ from sah_sdk.zyins import BUNDLED_API_VERSIONS
109
+
110
+ print(BUNDLED_API_VERSIONS)
111
+ # {
112
+ # "prequalify": "v2",
113
+ # "quote": "v2",
114
+ # "datasets": "v2",
115
+ # "reference": "v2",
116
+ # "sessions": "v1",
117
+ # "branding": "v1",
118
+ # "cases": "v1",
119
+ # }
120
+ ```
121
+
122
+ Pin individual surfaces with a per-surface `api_version` map. There is **no**
123
+ `default` key and **no** string shorthand — resolution is
124
+ `api_version.get(surface, BUNDLED_API_VERSIONS[surface])`:
125
+
126
+ ```python
127
+ isa = await Isa.with_keycode(
128
+ keycode="SDV-HWH-WDD",
129
+ email="john.doe@acme-agency.com",
130
+ api_version={"quote": "v2"}, # pin only quote; everything else bundled
131
+ )
132
+ ```
133
+
134
+ The release that retargets `prequalify` / `quote` / `datasets` / `reference`
135
+ to `v3` will bump those entries. See [SDK syntax proposal §2.7][syntax-27].
136
+
137
+ [syntax-27]: ../../docs/sdk-syntax-proposal.md#27-versioning--per-surface-not-global
138
+
139
+ ## Reference data — `.match()`
140
+
141
+ The unversioned `isa.zyins.reference` namespace canonicalizes free-text
142
+ medication and condition input. Unknown text never rejects — it returns a
143
+ structured envelope so the final canonicalization fires server-side at
144
+ `/vN/prequalify`:
145
+
146
+ ```python
147
+ ds = await isa.zyins.datasets.get(include=["conditions", "medications"])
148
+
149
+ insulin = isa.zyins.medications.match("insulin")
150
+ print(insulin.id, insulin.name, insulin.is_known)
151
+ # med_01KSR2WVAGC05ZGR6FA4QYEB12 INSULIN True
152
+
153
+ # Symmetric traversal — what conditions is insulin used for?
154
+ used_for = insulin.conditions(isa.zyins.reference.Sort.MOST_COMMON_FIRST)
155
+ # frequency-ordered list; cond_01KSR2WVAGC05ZGR6FA4QYEA8X first
156
+
157
+ novel = isa.zyins.medications.match("NewExperimental XR 2026")
158
+ # → {"is_known": False, "input_text": "NewExperimental XR 2026", ...}
159
+ ```
160
+
161
+ `Sort.MOST_COMMON_FIRST` and `Sort.ALPHABETICAL` are the two supported
162
+ orderings.
163
+
164
+ ## Case storage — bring your own
165
+
166
+ `isa.zyins.cases.*` routes through a `CaseStorage` adapter. The default is
167
+ the zero-knowledge store — ISA's servers only hold ciphertext and an opaque
168
+ ID. To plug a carrier-controlled store, pass your adapter at construction:
169
+
170
+ ```python
171
+ isa = await Isa.with_keycode(
172
+ keycode=..., email=...,
173
+ case_storage=CarrierCaseStorage(), # optional; default = ZeroKnowledgeCaseStorage
174
+ )
175
+ ```
176
+
177
+ See [cases guide](https://docs.isaapi.com/docs/cases) for the full
178
+ bring-your-own pattern.
179
+
180
+ ## Auth deviation from the TS SDK
181
+
182
+ The TypeScript SDK in this monorepo still carries the pre-#286 HMAC device
183
+ signing surface (`AuthContext` with `licenseKey + orderId + email + deviceId`).
184
+ The Python SDK is built against the post-#286 wire contract: a single
185
+ bearer token (`isa_live_*` / `isa_test_*`) is the entire auth surface.
186
+ This is the intentional simplification called out in the platform's
187
+ `platform_v1_architecture` notes.
188
+
189
+ ## Surface
190
+
191
+ | TypeScript | Python |
192
+ | ----------------------------------------- | ----------------------------------- |
193
+ | `client.prequalify(req)` | `client.prequalify.run(input)` |
194
+ | `client.license.activate/deactivate/check`| `client.license.*` (mirrored) |
195
+ | `client.case.email(req)` | `client.case.email(input)` |
196
+ | (new) | `client.quote.run(input)` |
197
+ | (new) | `client.datasets.list/get` |
198
+ | (new) | `client.reference_data.get(kind)` |
199
+ | (new) | `client.usage.summary(period)` |
200
+
201
+ Errors mirror the TS hierarchy: `ISAError` (alias `ZyInsError`, also
202
+ exported as `IsaApiError`) → `LicenseError`, `PrequalifyError`,
203
+ `ValidationError`, `RateLimitError`, `AuthError`,
204
+ `IsaIdempotencyConflictError`.
205
+
206
+ ## `Isa` factory client
207
+
208
+ Per [SDK_DESIGN.md §3](https://github.com/Software-Automation-Holdings-LLC/isa-platform/blob/main/docs/SDK_DESIGN.md),
209
+ the recommended entry point is the `Isa` class with three named factories:
210
+
211
+ ```python
212
+ from sah_sdk.zyins import Isa
213
+
214
+ # Reads ISA_TOKEN from the environment.
215
+ isa = Isa.with_bearer()
216
+ env = isa.zyins.prequalify(req)
217
+ print(env.data, env.request_id, env.idempotency_key, env.retry_attempts)
218
+
219
+ # Or pass the token explicitly.
220
+ isa = Isa.with_bearer("isa_live_…")
221
+
222
+ # License factory — reads ISA_LICENSE_KEYCODE / ISA_LICENSE_EMAIL.
223
+ isa = Isa.with_license()
224
+
225
+ # Session factory — reads ISA_SESSION_ID / ISA_SESSION_SECRET.
226
+ isa = Isa.with_session()
227
+ ```
228
+
229
+ Each factory raises `IsaConfigError` with a clear, actionable message if
230
+ the required env vars are unset and no explicit arguments are supplied.
231
+
232
+ ### Raw HTTP access
233
+
234
+ Every method has a `.with_raw_response()` variant returning both the
235
+ parsed envelope and the underlying HTTP metadata:
236
+
237
+ ```python
238
+ env, raw = isa.zyins.prequalify.with_raw_response(req)
239
+ raw.status # int
240
+ raw.url # str
241
+ raw.headers # read-only mapping
242
+ ```
243
+
244
+ ### Debug logging
245
+
246
+ Set `ISA_LOG=debug` to dump every request and response to **stderr** —
247
+ never stdout, so parent processes piping the consumer's JSON output stay
248
+ clean. Credential headers (`Authorization`, `X-Device-Signature`,
249
+ `X-Session-Signature`) and PII body fields (`email`, `dob`, `ssn`,
250
+ `phone`) are redacted automatically.
251
+
252
+ ### Idempotency conflicts
253
+
254
+ When the same `Idempotency-Key` is replayed with a different body the
255
+ server returns 409 `idempotency_conflict`. The SDK raises
256
+ `IsaIdempotencyConflictError` with `.key` and `.first_seen_at` so the
257
+ caller can audit the queued-write bug class:
258
+
259
+ ```python
260
+ from sah_sdk.zyins import IsaIdempotencyConflictError
261
+
262
+ try:
263
+ isa.zyins.prequalify(req, idempotency_key="case-42")
264
+ except IsaIdempotencyConflictError as e:
265
+ log.error("key %s first seen at %s", e.key, e.first_seen_at)
266
+ ```
267
+
268
+ ## Concurrency
269
+
270
+ The `Isa` client is safe for use with `asyncio.gather` and
271
+ `concurrent.futures` — every request mints a fresh request-id and
272
+ idempotency key, and shared client state (auth, base URL, debug logger)
273
+ is read-only after construction. Reuse a single `Isa` instance across
274
+ all concurrent requests; the underlying HTTP transport pools connections
275
+ for you.
276
+
277
+ ```python
278
+ import asyncio
279
+ from sah_sdk.zyins import Isa
280
+
281
+ isa = Isa.with_bearer()
282
+
283
+ async def one(req):
284
+ return isa.zyins.prequalify(req)
285
+
286
+ results = await asyncio.gather(*(one(r) for r in batch))
287
+ # Each result.request_id is distinct.
288
+ ```
289
+
290
+ ## Development
291
+
292
+ ```bash
293
+ hatch run test # pytest
294
+ hatch run lint # ruff + mypy --strict
295
+ hatch build # wheel + sdist
296
+ ```
297
+
298
+ Live-integration tests run only when `ZYINS_TEST_TOKEN` is set:
299
+
300
+ ```bash
301
+ ZYINS_TEST_TOKEN=isa_test_... hatch run test -- -m integration
302
+ ```
303
+
304
+ ## Licenses and Ready
305
+
306
+ The Python SDK exposes the public BPP license-lifecycle surface and the
307
+ platform readiness probe on every `ZyInsClient`:
308
+
309
+ ```python
310
+ from sah_sdk.zyins import LicenseCheckInput, ZyInsClient
311
+
312
+ client = ZyInsClient("isa_live_...")
313
+
314
+ result = client.license.check(
315
+ LicenseCheckInput(
316
+ email="john.doe@acme-agency.com",
317
+ keycode="ABC-123-XYZ",
318
+ device_id="dev_01HZK2N5GQR9T8X4B6FJW3Y1AS",
319
+ )
320
+ )
321
+ # result.status: "valid" | "invalid" | "inactive"
322
+
323
+ ready = client.health.get_readiness()
324
+ # ready.ready: True on every required probe = "serving"
325
+ ```
326
+
327
+ The pre-existing `client.license` (singular) sub-client targets the
328
+ authenticated `/v1/license/*` self-status endpoints and is untouched.
@@ -0,0 +1,100 @@
1
+ isa_sdk/__init__.py,sha256=NF_h4I2dLZoZlA8_-Ns4SIfINgtaSCeRyCRoIppXhxI,1817
2
+ isa_sdk/account.py,sha256=gBpA-w-3we2n5RtCdIRdlgU9efXQF-KtFCXjZSZpIsg,145
3
+ isa_sdk/catalog.py,sha256=pUHgV45njc_SLLOZMb8JzOwHTxyuT48tXFVq4QR12Wo,145
4
+ isa_sdk/core.py,sha256=qyJnqgW4umV7vzWtrkdEH7deh7UCNBe7XYbYOzJP_EU,136
5
+ isa_sdk/proxy.py,sha256=kWTMJCGD0A_8yQewLBF0Kh8dWhCIaQ1H1B2SMVpCuq8,139
6
+ isa_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ isa_sdk/rapidsign.py,sha256=62OZZ-DW4M8YpcOt2pHRJ-DowWrS0r06jGW95cQr7xg,151
8
+ isa_sdk/webhooks.py,sha256=MssU0sHdk0yyJrzMvil_LciDMRobcA5TkflTPE_A8Fs,148
9
+ isa_sdk/zyins.py,sha256=WDPGFM86sZlVeFzHoLNmyi9V6aUvRcw6M5eWAD8fkaQ,1052
10
+ sah_sdk/__contract__.py,sha256=R8DiukLXwZdVbcS97dK1pKDTiJJNynWy3TamN-51wyg,11810
11
+ sah_sdk/__init__.py,sha256=tev0wsnZ7OSh2sTWrxL_cPU-EzXgUV5w9ZO-2YueY18,3431
12
+ sah_sdk/isa.py,sha256=75NTfKXaB5OttGWTf7LMQpgKAxAMbnp_kvwlRSmsxTQ,61928
13
+ sah_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ sah_sdk/webhooks.py,sha256=i5SWFlObiEIzOgp5rfCjoH8waMQLHhRxvbsqwdPMYNQ,864
15
+ sah_sdk/_codemod/__init__.py,sha256=RpZlbHyFQRJpPI_8BUtClILMiWAzD_ENDbBdYH7e1jI,884
16
+ sah_sdk/_codemod/__main__.py,sha256=h6YqcMHNkColGbk4YnA5YjhTP-cwPjSQHYJQZGaaDKg,1302
17
+ sah_sdk/_codemod/rewriter.py,sha256=wGOTR__KGEPYkMt2FlBhNEZpd6gge7ZSd3HNjCoXxgQ,6586
18
+ sah_sdk/account/__init__.py,sha256=9N-4ZHSToefQnEBVYrQdauHcTYVYTUV-c5tyQIcJgmY,4073
19
+ sah_sdk/account/_op.py,sha256=V_4NzwBYCtKdz6Vf0Mx1jnHAewO-99VTptfLTux4xT8,2674
20
+ sah_sdk/account/branding.py,sha256=M-8nsTfP9CGodD7NTYG1K92IJmvGZNs6buUN4kmoqSw,3241
21
+ sah_sdk/account/cases.py,sha256=zvS35CSLEDWjYmkBkJ0dnScqQ6JRKGi_5ciHt1NwPv8,5411
22
+ sah_sdk/account/email.py,sha256=C0w8KIXWEMTvfXOIm-Ce8gMzLCkf0yW6_k8dFUfWW4I,3001
23
+ sah_sdk/account/preferences.py,sha256=8vFiMKUxF5pMdo7k0Bsacv7MuOxAGLQfZVkbGtje-1s,3129
24
+ sah_sdk/account/reference_data.py,sha256=aJ0MszcpjoUDA8DfnNggScKGEfb_mY190jdTbUlqIIo,3823
25
+ sah_sdk/catalog/__init__.py,sha256=xhSsBMcmMJmqgTpe9hZ4uNp7QpfKoCWXkNnCMDuPd04,1017
26
+ sah_sdk/catalog/carriers.py,sha256=--c4VYHnznF7w7YJOBUXG04aXY5CvnEz7xQNmMfI4Z8,13086
27
+ sah_sdk/catalog/conditions.py,sha256=qJYnUCngM2OrBracfQXBskkBADID5JpBlf0nf4ihO9I,1278
28
+ sah_sdk/catalog/errors.py,sha256=-6Lcf-ew91KcXyrzeHfJEmB97K60m-vrk6gN7HC6ENk,4017
29
+ sah_sdk/catalog/medications.py,sha256=2wTNm0dU3gSWBijijwQBSE8MwqF8lgpEG4BY8buUv3c,5131428
30
+ sah_sdk/catalog/products.py,sha256=s6oz2vCtSvg2oV1Q6m0njKgSn-kggw6QpzTQ6Kt1rgg,37663
31
+ sah_sdk/catalog/scopes.py,sha256=RqF3gHYOC_l8lcfqM4ASVTOGu9mEihfoJljAXIS89j0,1224
32
+ sah_sdk/catalog/sign_events.py,sha256=K9TPzHn0AdpjuMgoHuh7_2aXXFMjgctQnlt8jfbZSrE,599
33
+ sah_sdk/catalog/states.py,sha256=xsvmPKOl9evFt20qFbDAV19MsQqDZnwQRHNDPoYbG80,8839
34
+ sah_sdk/core/__init__.py,sha256=921k2f8LGo5bZG7ApMwKClqgK83YDHNE9P0leZpTgaU,1467
35
+ sah_sdk/core/auth.py,sha256=Y5H7oyggPTuaNORcI4fRXfPp_XFUyX_a9mL-RB8BBoI,3441
36
+ sah_sdk/core/bootstrap.py,sha256=ITMf_NJZr32iB8UjwdbWTgjuuJmHA0SDbLKRUAjg_0I,4849
37
+ sah_sdk/core/constants.py,sha256=defSzK9_QKnRrBGMS_1jaDE4H4MKpYRXEQ8P-nYpHbA,2967
38
+ sah_sdk/core/credential_store.py,sha256=xnZ9un3a4Het7HOZ67EaQJSNT-WDIA0J5yny18cxUgU,2941
39
+ sah_sdk/core/debug.py,sha256=oxwgsC3CGtvhVGUQ7WwAmqus-zC3JweAmimDsIllofE,4986
40
+ sah_sdk/core/env.py,sha256=c-fqP1B__l4gJ0r0jDSD75gL8dvyb03iz-msgja1qS8,2260
41
+ sah_sdk/core/envelope.py,sha256=_GTmJCli8DcFkNUvJVwUqZ2VodM1hn81-M5lTcVh6vM,2747
42
+ sah_sdk/core/errors.py,sha256=c4OMmG-5EXAjSDINBgrLaVSmn16YVCw0qi6AD0C4ycw,11935
43
+ sah_sdk/core/idempotency.py,sha256=EmlYl-n5VvQIRDdxig-4Ng2u7aBRC_NNl_Fq4d34H10,491
44
+ sah_sdk/core/json_response.py,sha256=7MErT5GjWfN3OGFsgxQwjxyt_aS_tWawXaS9Fpwe22s,1282
45
+ sah_sdk/core/license_hmac.py,sha256=VfYriveC_DcQcRQ_XpUqdgSLXiSI6l0GtEbCZ9WPpFY,4578
46
+ sah_sdk/core/session.py,sha256=PvxzQRRBR8BQIOD2TRn1AuAoDqnSEeh14tiI54yFqkU,11790
47
+ sah_sdk/core/sign_request.py,sha256=9ybfrWfhbNzI-dwuZDZNRF279fUA-8xDmPxIW3qDFF8,4043
48
+ sah_sdk/core/transport.py,sha256=n5xj_sd3dCbX1Upn5r8ofP2IavKSw3mQHQvRF_4O0jo,2727
49
+ sah_sdk/core/value_types.py,sha256=DPJOrPYtMzjZwo9CHI8z0xvYoeg_V3mDVAxD5I6yHUU,3275
50
+ sah_sdk/core/wire.py,sha256=kF-d3s8mN7z7S1xGq0Rg1ffYex_x0TV2eZkbeReuHHQ,2455
51
+ sah_sdk/proxy/__init__.py,sha256=FPp5YAFPTPLWWl9X3p6_b8gB67qlrwA6LsRfIE1AAbI,2769
52
+ sah_sdk/proxy/call.py,sha256=nImkj8TDj_ndF7GzfAa-lyFnBtt7KucPwk9aeMseJQg,9718
53
+ sah_sdk/rapidsign/__init__.py,sha256=CRRBS_5R-Aj8VscF1dZy0aRyJiGcWX74roUzznc9ojM,910
54
+ sah_sdk/zyins/__init__.py,sha256=DwJkBe5xZyXLD38M8Hl66vdOGWHbisg_XxnQismEEvw,5663
55
+ sah_sdk/zyins/account_namespaces.py,sha256=8rJxN5v7TwRI5CZZi-c5kGHZHBVwBeFODRIVCiCRs5g,4746
56
+ sah_sdk/zyins/applicant.py,sha256=OPsJapMb2xsJ8UWi0Eih8lh6K9ocuYgQMZo8w4Tn86E,6226
57
+ sah_sdk/zyins/branding.py,sha256=m9KTk6mdrGRXOH6m3ybr1mOaVRB7kTjqHC6crm_AGUI,2625
58
+ sah_sdk/zyins/bundled_api_versions.py,sha256=_NXMwLoxWphEmZyaX_uC6Db8jRISdefHObXi7htcfl0,2570
59
+ sah_sdk/zyins/cases.py,sha256=QC7nNqUN5LVA2Q16IEBs_Tqf6BlVvs5D_x33CCDqf6o,4393
60
+ sah_sdk/zyins/cases_storage.py,sha256=_Q483KFhxpDrK5XQi4fAw_DUlYfIs2PBSPOC1D20skg,731
61
+ sah_sdk/zyins/client.py,sha256=fmKCx2X7lQb9dbeXprnkQaFCaOSxV87PDrPRErcd_X8,14069
62
+ sah_sdk/zyins/coverage.py,sha256=4O37-KvAbYexW1c4CewtP-L2EP-Fp1mGsCmyuc1DxC8,3773
63
+ sah_sdk/zyins/credential_state.py,sha256=qrytgrpmut5GI8bFnAqNSbOLudB4h7NCg7VmZKsh9yg,5366
64
+ sah_sdk/zyins/datasets.py,sha256=DM611kkI1hRTEka8LrUixiHoPAvoVdwsH_K3YMe5x0M,1026
65
+ sah_sdk/zyins/datasets_v3.py,sha256=ejTzqieOqiaFHsJGFdqkOk4hgUeseWh6Bwl6gCxJFJQ,29132
66
+ sah_sdk/zyins/health.py,sha256=G2xgT0wE0d-VcQGxHyQ-DcUKolKx-OOvANnB6dLEBTQ,1345
67
+ sah_sdk/zyins/isa_options.py,sha256=gQZoolTOrEk-4lGnFYGbqtsjbvgt1trnp29unizq9v4,10724
68
+ sah_sdk/zyins/license.py,sha256=rM-67Y6MrNm8XZsJSYuZR-JP_m0d3jMuwiYsuNTIsZ4,1442
69
+ sah_sdk/zyins/licenses.py,sha256=Iry9lTWHBCos3cy0wTS7m8bx7fTokrcOgGUEMm9l9HE,3691
70
+ sah_sdk/zyins/licenses_facade.py,sha256=3KGdlef-fkWxwRbgTYXgyxjT-SjPRYnWwDjmD0aaUNg,8147
71
+ sah_sdk/zyins/logos.py,sha256=ZZyopkSUVRt3vnFCSY6VJyiku8aYfnuWflyBmd7wcC4,5061
72
+ sah_sdk/zyins/measurements.py,sha256=IxgfaTYWpC1QeDl6uW8gOYTViXFqTRrh12gy3Wak_Ho,10183
73
+ sah_sdk/zyins/plan_info_label.py,sha256=pSUCrXSwUbPJI9gQA5nDnhtveL6hVMkVhPDQVYcku1E,4641
74
+ sah_sdk/zyins/preferences.py,sha256=WTfM2ewulo_fjej3SojFNrZrdxjS8WiQT6DO9z94hug,2142
75
+ sah_sdk/zyins/prequalify.py,sha256=SRnk925h38h9T9Vi9ZEgnnmv3Zp6P_CWoC7GypSOdL8,9870
76
+ sah_sdk/zyins/prequalify_legacy_blob.py,sha256=NWIsV3rqLDSYloj0JHzikfDLucgz0JRA54ZzmqvBkBA,1733
77
+ sah_sdk/zyins/prequalify_v3.py,sha256=d1Lf1XQa8kLEGeq9zocLC_QurXyOZMpDtB4mZ_3oaqQ,32942
78
+ sah_sdk/zyins/product.py,sha256=lRI3e9FdTeSKfOa7RBVpOjjn0V7DyNYzivrrfpuzPVY,7476
79
+ sah_sdk/zyins/products.py,sha256=8px-1KrlXQIAd1l8Hse39zCuAzlHwTkD-SJkGBOSk0Q,1889
80
+ sah_sdk/zyins/quote.py,sha256=X494k12h1SBUh1xhU_GxXHXMWdSUKF87KCtCM0AkwcM,2473
81
+ sah_sdk/zyins/quote_v3.py,sha256=hmCnWfEaf0AJiMtaA4rYKnGFEbiqPQxJ3l8Caga6c1M,4835
82
+ sah_sdk/zyins/reference_data.py,sha256=1Op-OecASwKT8DoI6fvGiiZgflbBVh3QcRe1UcEjitY,1227
83
+ sah_sdk/zyins/reference_v3.py,sha256=_Y2dGY1Fj7p-SVXtbSrXKgZEJLRZiMqZVLvErcUXYgY,13863
84
+ sah_sdk/zyins/usage.py,sha256=2HWGXt_7d3w2Ca4Ays7AXDiOxI0X-lBaUeJmG9C9hbs,1042
85
+ sah_sdk/zyins/cases/__init__.py,sha256=Z2Ywv7LTpiBC-lYpDoD_pPNbQOwgIWdqOdzWxyDb6RU,8846
86
+ sah_sdk/zyins/cases/storage.py,sha256=lAcH9BxJiE7YDkRkV0MMWX_Db8kp1KM-hYB4v6rD3-4,3897
87
+ sah_sdk/zyins/cases/zero_knowledge.py,sha256=sqKvkhgppjUClQpy-v5U-fVuqCb5gR558SHeFFKeUBw,9646
88
+ sah_sdk/zyins/reference/__init__.py,sha256=49frt652UAuCm9zCBD7mhDVT9yYF7C4lSz9vQ1YaLh0,16342
89
+ sah_sdk/zyins/reference/_make_key.py,sha256=DKrY9TBvTaE-u48r7cqSBTuQ_KoKJkOyDZZKlU-wpmQ,1346
90
+ sah_sdk/zyins/reference/autocomplete_algorithm.py,sha256=b7ei4bAMo8Odxb-BNGmzEBTgrUzVxCDQN7RchI1q50Q,15784
91
+ sah_sdk/zyins/reference/autocorrector.py,sha256=0k5sR4dp5D_nev5vorLCM7r3zBdcXNU5xtVxrFcAC-E,12440
92
+ sah_sdk/zyins/reference/concept.py,sha256=JBGZM0wt8o1sFjzjKW3QPgi7NRI-38AGNHQo3mTq82M,6071
93
+ sah_sdk/zyins/reference/index.py,sha256=4TK0dmSmLeDmOoDHYSos1fMzWeby7QUMSgtg4_PtH4s,10234
94
+ sah_sdk/zyins/reference/match_algorithm.py,sha256=d3DkWEIPsKNlCSQ5RV9O_TEQHNEAaOCjuiqdPqUVu6s,3545
95
+ sah_sdk/zyins/reference/reference_index.py,sha256=CI8xFmY3n8z8f3qHLubgpFpKM_sc3sUihKEhoLR7aSM,9012
96
+ sah_sdk/zyins/reference/sort.py,sha256=22Ll3PvbFcT7MjMXI-SWLKVPDN0ceZE1tOgeKUnLM2c,937
97
+ sah_sdk/zyins/reference/suggestion.py,sha256=8j7Ij6iGLRojFJnKAhhLVJpW767Rv9wH2pY8P27ycfw,2375
98
+ isa_sdk-1.0.0.dist-info/METADATA,sha256=Y_LkVDI0nIwb9aP3TOfVs-ta6k8bTYf02G3rLeFXYzg,10771
99
+ isa_sdk-1.0.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
100
+ isa_sdk-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any