qnsi 0.3.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.
qnsi-0.3.0/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ # Python SDK build/test artifacts (mirrored to qnsp-public minus these)
2
+ .venv/
3
+ .pytest_cache/
4
+ .mypy_cache/
5
+ .ruff_cache/
6
+ __pycache__/
7
+ *.pyc
8
+ *.pyo
9
+ *.egg-info/
10
+ build/
11
+ dist/
qnsi-0.3.0/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+
17
+ Copyright 2026 HEOSSI (PTE.) LTD.
qnsi-0.3.0/PKG-INFO ADDED
@@ -0,0 +1,242 @@
1
+ Metadata-Version: 2.4
2
+ Name: qnsi
3
+ Version: 0.3.0
4
+ Summary: Official Python SDK for the QNSI Quantum-Native Security Infrastructure — post-quantum cryptography (ML-KEM, ML-DSA, SLH-DSA, Falcon via liboqs), PQC-encrypted vault, KMS, and immutable audit trails. Mirrors the @heossi/qnsi-* TypeScript SDKs.
5
+ Project-URL: Homepage, https://cloud.qnsi.heossi.com
6
+ Project-URL: Documentation, https://docs.qnsi.heossi.com/sdk/python
7
+ Project-URL: Repository, https://github.com/heossi-hq/qnsi-public
8
+ Project-URL: Issues, https://github.com/heossi-hq/qnsi-public/issues
9
+ Project-URL: Changelog, https://github.com/heossi-hq/qnsi-public/blob/main/sdks/python/qnsi/CHANGELOG.md
10
+ Author: HEOSSI (PTE.) LTD.
11
+ License: Apache-2.0
12
+ License-File: LICENSE
13
+ Keywords: audit,compliance,falcon,fips-203,fips-204,fips-205,kms,liboqs,ml-dsa,ml-kem,post-quantum,post-quantum-cryptography,pqc,qnsi,quantum-safe,slh-dsa,vault,zero-trust
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: Information Technology
17
+ Classifier: License :: OSI Approved :: Apache Software License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3 :: Only
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: Security :: Cryptography
26
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.10
29
+ Requires-Dist: httpx<1.0,>=0.27
30
+ Requires-Dist: pyjwt<3.0,>=2.8
31
+ Provides-Extra: all
32
+ Requires-Dist: liboqs-python==0.12.0; extra == 'all'
33
+ Provides-Extra: crypto
34
+ Requires-Dist: liboqs-python==0.12.0; extra == 'crypto'
35
+ Provides-Extra: dev
36
+ Requires-Dist: mypy>=1.10; extra == 'dev'
37
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
38
+ Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
39
+ Requires-Dist: pytest>=8.0; extra == 'dev'
40
+ Requires-Dist: ruff>=0.6; extra == 'dev'
41
+ Description-Content-Type: text/markdown
42
+
43
+ # qnsp — Python SDK for the Quantum-Native Security Infrastructure
44
+
45
+ [![PyPI version](https://img.shields.io/pypi/v/qnsp.svg)](https://pypi.org/project/qnsp/)
46
+ [![Python versions](https://img.shields.io/pypi/pyversions/qnsp.svg)](https://pypi.org/project/qnsp/)
47
+ [![License](https://img.shields.io/pypi/l/qnsp.svg)](./LICENSE)
48
+
49
+ Typed Python client for QNSI — post-quantum cryptography (ML-KEM, ML-DSA, SLH-DSA, Falcon via liboqs), PQC-encrypted vault, server-side KMS, immutable audit trails. Same wire contracts as the official `@heossi/qnsi-*` TypeScript SDKs — pick whichever language fits your stack and the byte-for-byte outputs round-trip.
50
+
51
+ > **Free tier available.** Free-forever account at <https://cloud.qnsi.heossi.com/auth> — 60-second signup, no credit card. Includes 10 GB PQC storage, 50 000 API calls/month, 20 KMS keys, 25 vault secrets.
52
+
53
+ ## Installation
54
+
55
+ Base install (HTTP clients for vault, KMS, audit):
56
+
57
+ ```bash
58
+ pip install qnsp
59
+ ```
60
+
61
+ With local PQC primitives (`qnsp.crypto` — wraps `liboqs-python` 0.12.0):
62
+
63
+ ```bash
64
+ pip install 'qnsi[crypto]'
65
+ ```
66
+
67
+ `liboqs-python` requires the `liboqs` C library available on the host. Easiest paths:
68
+
69
+ | Platform | Command |
70
+ | --- | --- |
71
+ | macOS | `brew install liboqs` |
72
+ | Debian/Ubuntu | `apt install liboqs-dev` |
73
+ | From source | `cmake -DBUILD_SHARED_LIBS=ON ...` — see <https://github.com/open-quantum-safe/liboqs> |
74
+
75
+ (A v0.3.x release will ship `cibuildwheel`-built wheels that bundle a self-contained liboqs binary, removing the system prerequisite.)
76
+
77
+ Requires Python 3.10+ and `httpx`. Tested on CPython 3.10, 3.11, 3.12, 3.13.
78
+
79
+ ## Quick start
80
+
81
+ ```python
82
+ import os
83
+ import base64
84
+
85
+ from qnsi import QnspClient
86
+
87
+ with QnspClient(api_key=os.environ["QNSP_API_KEY"]) as qnsp:
88
+ # ── Vault — PQC-encrypted secret storage ─────────────────────────
89
+ secret = qnsp.vault.create_secret(
90
+ name="openai-api-key",
91
+ payload_b64=base64.b64encode(b"sk-...").decode(),
92
+ algorithm="ml-kem-768",
93
+ )
94
+ fresh = qnsp.vault.get_secret(secret["id"])
95
+
96
+ # ── KMS — server-side PQC keys ──────────────────────────────────
97
+ key = qnsp.kms.create_key(algorithm="ml-dsa-65", purpose="signing")
98
+ signature = qnsp.kms.sign(key["keyId"], data=b"hello")
99
+ assert qnsp.kms.verify(key["keyId"], data=b"hello", signature=signature)
100
+
101
+ # ── Audit — immutable, hash-chained event log ───────────────────
102
+ qnsp.audit.log_event(
103
+ event_type="model.inference",
104
+ payload={"modelId": "gpt-4o", "latencyMs": 412},
105
+ )
106
+
107
+ # ── New in 0.3.0 — full parity with Go and Rust SDKs ────────────
108
+ qnsp.tenant.get_tenant(qnsp.tenant_id)
109
+ qnsp.access.check_permission(subject_id="user-1", permission="vault.read")
110
+ qnsp.billing.get_entitlements()
111
+ qnsp.crypto_inventory.get_readiness_score(qnsp.tenant_id)
112
+ qnsp.storage.put_object("uploads", "report.pdf", data=b"...")
113
+ qnsp.search.query("docs", vector=[0.1] * 768, top_k=5)
114
+ qnsp.ai.invoke_inference(model_id="gpt-4o", input={"prompt": "..."})
115
+ qnsp.auth.login(email="user@example.com", password="...", tenant_id=qnsp.tenant_id)
116
+ ```
117
+
118
+ ## Local PQC primitives
119
+
120
+ `qnsp.crypto` wraps `liboqs-python` so you don't have to write `oqs` calls yourself, and so the algorithm-name surface matches the rest of the QNSI ecosystem (TypeScript, Go, Rust):
121
+
122
+ ```python
123
+ from qnsi.crypto import MlKem, MlDsa, SlhDsa, Falcon
124
+
125
+ # Module-Lattice KEM (FIPS 203)
126
+ kem = MlKem("ML-KEM-768")
127
+ pk, sk = kem.keygen()
128
+ enc = kem.encapsulate(pk)
129
+ recovered = kem.decapsulate(enc.ciphertext, sk)
130
+ assert recovered == enc.shared_secret
131
+
132
+ # Module-Lattice signatures (FIPS 204)
133
+ sig = MlDsa("ML-DSA-65")
134
+ sig_pk, sig_sk = sig.keygen()
135
+ signature = sig.sign(b"hello", sig_sk)
136
+ assert sig.verify(b"hello", signature, sig_pk)
137
+
138
+ # Stateless hash-based signatures (FIPS 205) — conservative, no lattice assumption
139
+ slh = SlhDsa("SLH-DSA-SHA2-128f")
140
+
141
+ # Compact lattice signatures (NIST PQC selection)
142
+ fal = Falcon("Falcon-512")
143
+ ```
144
+
145
+ Sizes match the FIPS specs exactly (the SDK reads them from the linked liboqs build, so no inline literals drift).
146
+
147
+ ## Verifying inbound webhooks
148
+
149
+ QNSI signs every webhook with HMAC-SHA-256. Verify the **raw body** before parsing JSON:
150
+
151
+ ```python
152
+ from fastapi import FastAPI, Request, HTTPException
153
+ from qnsi import parse_qnsp_webhook, QnspWebhookError
154
+
155
+ app = FastAPI()
156
+
157
+ @app.post("/webhooks/qnsp")
158
+ async def receive(request: Request) -> dict:
159
+ body = await request.body()
160
+ try:
161
+ event = parse_qnsp_webhook(
162
+ body=body,
163
+ signature_header=request.headers.get("x-qnsp-signature", ""),
164
+ timestamp_header=request.headers.get("x-qnsp-timestamp"),
165
+ secret=os.environ["QNSP_WEBHOOK_SECRET"],
166
+ )
167
+ except QnspWebhookError as exc:
168
+ raise HTTPException(400, str(exc))
169
+
170
+ if event.event_type == "key.rotated":
171
+ ...
172
+ return {"ok": True}
173
+ ```
174
+
175
+ The verifier runs HMAC comparison in constant time, rejects timestamps older than 5 minutes by default (replay protection), and refuses payloads missing required fields.
176
+
177
+ ## Error handling
178
+
179
+ All errors descend from `qnsp.QnspError`:
180
+
181
+ | Class | When |
182
+ | --- | --- |
183
+ | `QnspNetworkError` | DNS, TLS, timeout, or connection failure |
184
+ | `QnspAuthError` | API key rejected at activation |
185
+ | `QnspApiError` | A service returned 4xx/5xx with a structured body |
186
+ | `QnspWebhookError` | HMAC mismatch, expired timestamp, malformed body, etc. |
187
+
188
+ ```python
189
+ from qnsi import QnspApiError, QnspNetworkError
190
+
191
+ try:
192
+ qnsp.vault.get_secret("missing")
193
+ except QnspApiError as exc:
194
+ print("HTTP", exc.status_code, exc.code, exc.body)
195
+ except QnspNetworkError as exc:
196
+ print("Could not reach QNSI:", exc)
197
+ ```
198
+
199
+ ## Activation + tier introspection
200
+
201
+ `QnspClient` performs a one-shot handshake against `/billing/v1/sdk/activate` on first use. The result is cached in memory; subsequent calls reuse it until ~1 minute before expiry. You can inspect the current activation:
202
+
203
+ ```python
204
+ qnsp.tenant_id # resolved tenant
205
+ qnsp.tier # plan tier
206
+ qnsp.limits # full limits dict
207
+ qnsp.has_feature("sseEnabled") # convenience boolean
208
+ ```
209
+
210
+ If the activation token is rotated server-side, the SDK invalidates its cache and retries the originating request once on a 401.
211
+
212
+ ## What's covered today (v0.3.0 — full parity with Go and Rust SDKs)
213
+
214
+ Customer-facing service modules — every QNSI service callable through the edge gateway:
215
+
216
+ - `qnsp.vault` — secrets management (create / get / get-version / rotate / delete / list-versions)
217
+ - `qnsp.kms` — server-side PQC keys (create / list / get / rotate / delete / sign / verify / wrap / unwrap)
218
+ - `qnsp.audit` — immutable hash-chained event log (log-event / ingest-events / list-events)
219
+ - `qnsp.auth` — login, refresh, revoke, WebAuthn passkeys, MFA, SAML/OIDC federation, risk-based auth
220
+ - `qnsp.tenant` — tenant CRUD, crypto-policy management, current-health, current-quotas
221
+ - `qnsp.access` — RBAC roles, role assignments, `check_permission`
222
+ - `qnsp.billing` — entitlements, usage meters (single + batch), invoice listing, credit balance
223
+ - `qnsp.crypto_inventory` — Cryptographic Bill of Materials: assets, discovery runs, PQC readiness
224
+ - `qnsp.storage` — PQC-encrypted object storage with SSE-X
225
+ - `qnsp.search` — encrypted vector search (index lifecycle, `upsert_vectors`, `query`)
226
+ - `qnsp.ai` — model registry, AI workloads with enclave attestation, `invoke_inference`, artifacts
227
+
228
+ Local primitives + integration:
229
+
230
+ - `qnsp.crypto` (requires `qnsi[crypto]`) — ML-KEM (512/768/1024), ML-DSA (44/65/87), SLH-DSA (8 variants), Falcon (512/1024), plus BIKE, FrodoKEM, Classic-McEliece, MAYO, CROSS — every FIPS 203/204/205 finalist exposed by liboqs 0.12.0
231
+ - `qnsp.parse_qnsp_webhook` / `qnsp.verify_qnsp_webhook_signature` — HMAC-SHA-256 verify + replay protection
232
+ - `qnsp.QnspClient` — API-key activation with caching and 401 retry
233
+
234
+ ## What's coming
235
+
236
+ - `AsyncQnspClient` — native-async variants using `httpx.AsyncClient`
237
+ - A `pytest` plugin that mocks the QNSI API for tests in your codebase
238
+ - Generated typed responses (currently `dict[str, Any]`) for every method
239
+
240
+ ## License
241
+
242
+ Apache-2.0. See [LICENSE](./LICENSE).
qnsi-0.3.0/README.md ADDED
@@ -0,0 +1,200 @@
1
+ # qnsp — Python SDK for the Quantum-Native Security Infrastructure
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/qnsp.svg)](https://pypi.org/project/qnsp/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/qnsp.svg)](https://pypi.org/project/qnsp/)
5
+ [![License](https://img.shields.io/pypi/l/qnsp.svg)](./LICENSE)
6
+
7
+ Typed Python client for QNSI — post-quantum cryptography (ML-KEM, ML-DSA, SLH-DSA, Falcon via liboqs), PQC-encrypted vault, server-side KMS, immutable audit trails. Same wire contracts as the official `@heossi/qnsi-*` TypeScript SDKs — pick whichever language fits your stack and the byte-for-byte outputs round-trip.
8
+
9
+ > **Free tier available.** Free-forever account at <https://cloud.qnsi.heossi.com/auth> — 60-second signup, no credit card. Includes 10 GB PQC storage, 50 000 API calls/month, 20 KMS keys, 25 vault secrets.
10
+
11
+ ## Installation
12
+
13
+ Base install (HTTP clients for vault, KMS, audit):
14
+
15
+ ```bash
16
+ pip install qnsp
17
+ ```
18
+
19
+ With local PQC primitives (`qnsp.crypto` — wraps `liboqs-python` 0.12.0):
20
+
21
+ ```bash
22
+ pip install 'qnsi[crypto]'
23
+ ```
24
+
25
+ `liboqs-python` requires the `liboqs` C library available on the host. Easiest paths:
26
+
27
+ | Platform | Command |
28
+ | --- | --- |
29
+ | macOS | `brew install liboqs` |
30
+ | Debian/Ubuntu | `apt install liboqs-dev` |
31
+ | From source | `cmake -DBUILD_SHARED_LIBS=ON ...` — see <https://github.com/open-quantum-safe/liboqs> |
32
+
33
+ (A v0.3.x release will ship `cibuildwheel`-built wheels that bundle a self-contained liboqs binary, removing the system prerequisite.)
34
+
35
+ Requires Python 3.10+ and `httpx`. Tested on CPython 3.10, 3.11, 3.12, 3.13.
36
+
37
+ ## Quick start
38
+
39
+ ```python
40
+ import os
41
+ import base64
42
+
43
+ from qnsi import QnspClient
44
+
45
+ with QnspClient(api_key=os.environ["QNSP_API_KEY"]) as qnsp:
46
+ # ── Vault — PQC-encrypted secret storage ─────────────────────────
47
+ secret = qnsp.vault.create_secret(
48
+ name="openai-api-key",
49
+ payload_b64=base64.b64encode(b"sk-...").decode(),
50
+ algorithm="ml-kem-768",
51
+ )
52
+ fresh = qnsp.vault.get_secret(secret["id"])
53
+
54
+ # ── KMS — server-side PQC keys ──────────────────────────────────
55
+ key = qnsp.kms.create_key(algorithm="ml-dsa-65", purpose="signing")
56
+ signature = qnsp.kms.sign(key["keyId"], data=b"hello")
57
+ assert qnsp.kms.verify(key["keyId"], data=b"hello", signature=signature)
58
+
59
+ # ── Audit — immutable, hash-chained event log ───────────────────
60
+ qnsp.audit.log_event(
61
+ event_type="model.inference",
62
+ payload={"modelId": "gpt-4o", "latencyMs": 412},
63
+ )
64
+
65
+ # ── New in 0.3.0 — full parity with Go and Rust SDKs ────────────
66
+ qnsp.tenant.get_tenant(qnsp.tenant_id)
67
+ qnsp.access.check_permission(subject_id="user-1", permission="vault.read")
68
+ qnsp.billing.get_entitlements()
69
+ qnsp.crypto_inventory.get_readiness_score(qnsp.tenant_id)
70
+ qnsp.storage.put_object("uploads", "report.pdf", data=b"...")
71
+ qnsp.search.query("docs", vector=[0.1] * 768, top_k=5)
72
+ qnsp.ai.invoke_inference(model_id="gpt-4o", input={"prompt": "..."})
73
+ qnsp.auth.login(email="user@example.com", password="...", tenant_id=qnsp.tenant_id)
74
+ ```
75
+
76
+ ## Local PQC primitives
77
+
78
+ `qnsp.crypto` wraps `liboqs-python` so you don't have to write `oqs` calls yourself, and so the algorithm-name surface matches the rest of the QNSI ecosystem (TypeScript, Go, Rust):
79
+
80
+ ```python
81
+ from qnsi.crypto import MlKem, MlDsa, SlhDsa, Falcon
82
+
83
+ # Module-Lattice KEM (FIPS 203)
84
+ kem = MlKem("ML-KEM-768")
85
+ pk, sk = kem.keygen()
86
+ enc = kem.encapsulate(pk)
87
+ recovered = kem.decapsulate(enc.ciphertext, sk)
88
+ assert recovered == enc.shared_secret
89
+
90
+ # Module-Lattice signatures (FIPS 204)
91
+ sig = MlDsa("ML-DSA-65")
92
+ sig_pk, sig_sk = sig.keygen()
93
+ signature = sig.sign(b"hello", sig_sk)
94
+ assert sig.verify(b"hello", signature, sig_pk)
95
+
96
+ # Stateless hash-based signatures (FIPS 205) — conservative, no lattice assumption
97
+ slh = SlhDsa("SLH-DSA-SHA2-128f")
98
+
99
+ # Compact lattice signatures (NIST PQC selection)
100
+ fal = Falcon("Falcon-512")
101
+ ```
102
+
103
+ Sizes match the FIPS specs exactly (the SDK reads them from the linked liboqs build, so no inline literals drift).
104
+
105
+ ## Verifying inbound webhooks
106
+
107
+ QNSI signs every webhook with HMAC-SHA-256. Verify the **raw body** before parsing JSON:
108
+
109
+ ```python
110
+ from fastapi import FastAPI, Request, HTTPException
111
+ from qnsi import parse_qnsp_webhook, QnspWebhookError
112
+
113
+ app = FastAPI()
114
+
115
+ @app.post("/webhooks/qnsp")
116
+ async def receive(request: Request) -> dict:
117
+ body = await request.body()
118
+ try:
119
+ event = parse_qnsp_webhook(
120
+ body=body,
121
+ signature_header=request.headers.get("x-qnsp-signature", ""),
122
+ timestamp_header=request.headers.get("x-qnsp-timestamp"),
123
+ secret=os.environ["QNSP_WEBHOOK_SECRET"],
124
+ )
125
+ except QnspWebhookError as exc:
126
+ raise HTTPException(400, str(exc))
127
+
128
+ if event.event_type == "key.rotated":
129
+ ...
130
+ return {"ok": True}
131
+ ```
132
+
133
+ The verifier runs HMAC comparison in constant time, rejects timestamps older than 5 minutes by default (replay protection), and refuses payloads missing required fields.
134
+
135
+ ## Error handling
136
+
137
+ All errors descend from `qnsp.QnspError`:
138
+
139
+ | Class | When |
140
+ | --- | --- |
141
+ | `QnspNetworkError` | DNS, TLS, timeout, or connection failure |
142
+ | `QnspAuthError` | API key rejected at activation |
143
+ | `QnspApiError` | A service returned 4xx/5xx with a structured body |
144
+ | `QnspWebhookError` | HMAC mismatch, expired timestamp, malformed body, etc. |
145
+
146
+ ```python
147
+ from qnsi import QnspApiError, QnspNetworkError
148
+
149
+ try:
150
+ qnsp.vault.get_secret("missing")
151
+ except QnspApiError as exc:
152
+ print("HTTP", exc.status_code, exc.code, exc.body)
153
+ except QnspNetworkError as exc:
154
+ print("Could not reach QNSI:", exc)
155
+ ```
156
+
157
+ ## Activation + tier introspection
158
+
159
+ `QnspClient` performs a one-shot handshake against `/billing/v1/sdk/activate` on first use. The result is cached in memory; subsequent calls reuse it until ~1 minute before expiry. You can inspect the current activation:
160
+
161
+ ```python
162
+ qnsp.tenant_id # resolved tenant
163
+ qnsp.tier # plan tier
164
+ qnsp.limits # full limits dict
165
+ qnsp.has_feature("sseEnabled") # convenience boolean
166
+ ```
167
+
168
+ If the activation token is rotated server-side, the SDK invalidates its cache and retries the originating request once on a 401.
169
+
170
+ ## What's covered today (v0.3.0 — full parity with Go and Rust SDKs)
171
+
172
+ Customer-facing service modules — every QNSI service callable through the edge gateway:
173
+
174
+ - `qnsp.vault` — secrets management (create / get / get-version / rotate / delete / list-versions)
175
+ - `qnsp.kms` — server-side PQC keys (create / list / get / rotate / delete / sign / verify / wrap / unwrap)
176
+ - `qnsp.audit` — immutable hash-chained event log (log-event / ingest-events / list-events)
177
+ - `qnsp.auth` — login, refresh, revoke, WebAuthn passkeys, MFA, SAML/OIDC federation, risk-based auth
178
+ - `qnsp.tenant` — tenant CRUD, crypto-policy management, current-health, current-quotas
179
+ - `qnsp.access` — RBAC roles, role assignments, `check_permission`
180
+ - `qnsp.billing` — entitlements, usage meters (single + batch), invoice listing, credit balance
181
+ - `qnsp.crypto_inventory` — Cryptographic Bill of Materials: assets, discovery runs, PQC readiness
182
+ - `qnsp.storage` — PQC-encrypted object storage with SSE-X
183
+ - `qnsp.search` — encrypted vector search (index lifecycle, `upsert_vectors`, `query`)
184
+ - `qnsp.ai` — model registry, AI workloads with enclave attestation, `invoke_inference`, artifacts
185
+
186
+ Local primitives + integration:
187
+
188
+ - `qnsp.crypto` (requires `qnsi[crypto]`) — ML-KEM (512/768/1024), ML-DSA (44/65/87), SLH-DSA (8 variants), Falcon (512/1024), plus BIKE, FrodoKEM, Classic-McEliece, MAYO, CROSS — every FIPS 203/204/205 finalist exposed by liboqs 0.12.0
189
+ - `qnsp.parse_qnsp_webhook` / `qnsp.verify_qnsp_webhook_signature` — HMAC-SHA-256 verify + replay protection
190
+ - `qnsp.QnspClient` — API-key activation with caching and 401 retry
191
+
192
+ ## What's coming
193
+
194
+ - `AsyncQnspClient` — native-async variants using `httpx.AsyncClient`
195
+ - A `pytest` plugin that mocks the QNSI API for tests in your codebase
196
+ - Generated typed responses (currently `dict[str, Any]`) for every method
197
+
198
+ ## License
199
+
200
+ Apache-2.0. See [LICENSE](./LICENSE).
@@ -0,0 +1,108 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "qnsi"
7
+ version = "0.3.0"
8
+ description = "Official Python SDK for the QNSI Quantum-Native Security Infrastructure — post-quantum cryptography (ML-KEM, ML-DSA, SLH-DSA, Falcon via liboqs), PQC-encrypted vault, KMS, and immutable audit trails. Mirrors the @heossi/qnsi-* TypeScript SDKs."
9
+ readme = "README.md"
10
+ license = { text = "Apache-2.0" }
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "HEOSSI (PTE.) LTD." },
14
+ ]
15
+ keywords = [
16
+ "qnsi",
17
+ "post-quantum",
18
+ "post-quantum-cryptography",
19
+ "pqc",
20
+ "vault",
21
+ "kms",
22
+ "audit",
23
+ "compliance",
24
+ "fips-203",
25
+ "fips-204",
26
+ "fips-205",
27
+ "ml-kem",
28
+ "ml-dsa",
29
+ "slh-dsa",
30
+ "falcon",
31
+ "liboqs",
32
+ "quantum-safe",
33
+ "zero-trust",
34
+ ]
35
+ classifiers = [
36
+ "Development Status :: 4 - Beta",
37
+ "Intended Audience :: Developers",
38
+ "Intended Audience :: Information Technology",
39
+ "License :: OSI Approved :: Apache Software License",
40
+ "Operating System :: OS Independent",
41
+ "Programming Language :: Python :: 3",
42
+ "Programming Language :: Python :: 3 :: Only",
43
+ "Programming Language :: Python :: 3.10",
44
+ "Programming Language :: Python :: 3.11",
45
+ "Programming Language :: Python :: 3.12",
46
+ "Programming Language :: Python :: 3.13",
47
+ "Topic :: Security :: Cryptography",
48
+ "Topic :: Software Development :: Libraries :: Python Modules",
49
+ "Typing :: Typed",
50
+ ]
51
+ dependencies = [
52
+ "httpx>=0.27,<1.0",
53
+ "PyJWT>=2.8,<3.0",
54
+ ]
55
+
56
+ [project.optional-dependencies]
57
+ # Local PQC primitives — wraps liboqs via the open-quantum-safe Python binding.
58
+ # `liboqs-python` 0.12.0 expects the liboqs C library to be discoverable on the
59
+ # system. Inside the QNSI monorepo this is satisfied automatically by
60
+ # `tooling/liboqs-src/build/`. End users install via:
61
+ # - macOS: brew install liboqs && pip install 'qnsi[crypto]'
62
+ # - Debian: apt install liboqs-dev && pip install 'qnsi[crypto]'
63
+ # - Other: build liboqs from source (see https://github.com/open-quantum-safe/liboqs)
64
+ # A v0.3.x follow-up will ship cibuildwheel-built wheels that bundle a fully
65
+ # self-contained liboqs binary — same model as @heossi/liboqs-native's prebuilds/.
66
+ crypto = [
67
+ "liboqs-python==0.12.0",
68
+ ]
69
+ dev = [
70
+ "pytest>=8.0",
71
+ "pytest-asyncio>=0.23",
72
+ "pytest-httpx>=0.30",
73
+ "mypy>=1.10",
74
+ "ruff>=0.6",
75
+ ]
76
+ all = [
77
+ "qnsi[crypto]",
78
+ ]
79
+
80
+ [project.urls]
81
+ Homepage = "https://cloud.qnsi.heossi.com"
82
+ Documentation = "https://docs.qnsi.heossi.com/sdk/python"
83
+ Repository = "https://github.com/heossi-hq/qnsi-public"
84
+ Issues = "https://github.com/heossi-hq/qnsi-public/issues"
85
+ Changelog = "https://github.com/heossi-hq/qnsi-public/blob/main/sdks/python/qnsi/CHANGELOG.md"
86
+
87
+ [tool.hatch.build.targets.wheel]
88
+ packages = ["src/qnsi"]
89
+
90
+ [tool.hatch.build.targets.sdist]
91
+ include = ["src", "README.md", "LICENSE", "pyproject.toml"]
92
+
93
+ [tool.ruff]
94
+ line-length = 100
95
+ target-version = "py310"
96
+
97
+ [tool.ruff.lint]
98
+ select = ["E", "F", "W", "I", "N", "UP", "B", "C4", "SIM", "RUF"]
99
+
100
+ [tool.mypy]
101
+ python_version = "3.10"
102
+ strict = true
103
+ warn_return_any = true
104
+ warn_unused_configs = true
105
+
106
+ [tool.pytest.ini_options]
107
+ testpaths = ["tests"]
108
+ asyncio_mode = "auto"
@@ -0,0 +1,98 @@
1
+ """QNSI — official Python SDK for the Quantum-Native Security Infrastructure.
2
+
3
+ Mirrors the surface of the ``@heossi/qnsi-*`` TypeScript SDK family for the Python
4
+ ecosystem. Same wire contracts, same algorithm names, same FIPS 203/204/205
5
+ posture — pick whichever language fits your stack and the byte-for-byte
6
+ outputs round-trip.
7
+
8
+ Quick start::
9
+
10
+ from qnsi import QnspClient
11
+
12
+ qnsp = QnspClient(api_key=os.environ["QNSP_API_KEY"])
13
+
14
+ # Vault
15
+ secret = qnsp.vault.create_secret(
16
+ name="openai-key",
17
+ payload_b64=base64.b64encode(b"sk-...").decode(),
18
+ )
19
+
20
+ # KMS
21
+ key = qnsp.kms.create_key(algorithm="ml-dsa-65", purpose="signing")
22
+ sig = qnsp.kms.sign(key["keyId"], data=b"hello")
23
+
24
+ # Audit
25
+ qnsp.audit.log_event(event_type="model.inference", payload={"modelId": "gpt-4o"})
26
+
27
+ Local PQC primitives (requires ``qnsi[crypto]``)::
28
+
29
+ from qnsi.crypto import MlKem, MlDsa
30
+
31
+ kem = MlKem("ML-KEM-768")
32
+ pk, sk = kem.keygen()
33
+ enc = kem.encapsulate(pk)
34
+ assert kem.decapsulate(enc.ciphertext, sk) == enc.shared_secret
35
+
36
+ Webhook verification::
37
+
38
+ from qnsi import parse_qnsp_webhook, QnspWebhookError
39
+
40
+ event = parse_qnsp_webhook(
41
+ body=raw_body,
42
+ signature_header=request.headers["x-qnsp-signature"],
43
+ timestamp_header=request.headers["x-qnsp-timestamp"],
44
+ secret=os.environ["QNSP_WEBHOOK_SECRET"],
45
+ )
46
+
47
+ Free signup at https://cloud.qnsi.heossi.com/auth — no credit card.
48
+ """
49
+
50
+ from qnsi._client import QnspClient
51
+ from qnsi._errors import (
52
+ QnspApiError,
53
+ QnspAuthError,
54
+ QnspError,
55
+ QnspNetworkError,
56
+ QnspWebhookError,
57
+ )
58
+ from qnsi.access import AccessClient
59
+ from qnsi.ai import AIClient
60
+ from qnsi.audit import AuditClient
61
+ from qnsi.auth import AuthClient
62
+ from qnsi.billing import BillingClient
63
+ from qnsi.crypto_inventory import CryptoInventoryClient
64
+ from qnsi.kms import KmsClient
65
+ from qnsi.search import SearchClient
66
+ from qnsi.storage import StorageClient
67
+ from qnsi.tenant import TenantClient
68
+ from qnsi.vault import VaultClient
69
+ from qnsi.webhooks import (
70
+ QnspWebhookEvent,
71
+ parse_qnsp_webhook,
72
+ verify_qnsp_webhook_signature,
73
+ )
74
+
75
+ __version__ = "0.3.0"
76
+
77
+ __all__ = [
78
+ "AccessClient",
79
+ "AIClient",
80
+ "AuditClient",
81
+ "AuthClient",
82
+ "BillingClient",
83
+ "CryptoInventoryClient",
84
+ "KmsClient",
85
+ "QnspApiError",
86
+ "QnspAuthError",
87
+ "QnspClient",
88
+ "QnspError",
89
+ "QnspNetworkError",
90
+ "QnspWebhookError",
91
+ "QnspWebhookEvent",
92
+ "SearchClient",
93
+ "StorageClient",
94
+ "TenantClient",
95
+ "VaultClient",
96
+ "parse_qnsp_webhook",
97
+ "verify_qnsp_webhook_signature",
98
+ ]