@heossi/qnsi 0.3.2
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.
- package/CHANGELOG.md +67 -0
- package/LICENSE.md +8 -0
- package/README.md +200 -0
- package/dist/_activation/activation-client.d.ts +65 -0
- package/dist/_activation/activation-client.d.ts.map +1 -0
- package/dist/_activation/activation-client.js +164 -0
- package/dist/_activation/activation-client.js.map +1 -0
- package/dist/_activation/index.d.ts +10 -0
- package/dist/_activation/index.d.ts.map +1 -0
- package/dist/_activation/index.js +10 -0
- package/dist/_activation/index.js.map +1 -0
- package/dist/_activation/types.d.ts +128 -0
- package/dist/_activation/types.d.ts.map +1 -0
- package/dist/_activation/types.js +94 -0
- package/dist/_activation/types.js.map +1 -0
- package/dist/_internal.d.ts +52 -0
- package/dist/_internal.d.ts.map +1 -0
- package/dist/_internal.js +235 -0
- package/dist/_internal.js.map +1 -0
- package/dist/access.d.ts +32 -0
- package/dist/access.d.ts.map +1 -0
- package/dist/access.js +33 -0
- package/dist/access.js.map +1 -0
- package/dist/ai.d.ts +51 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +53 -0
- package/dist/ai.js.map +1 -0
- package/dist/audit.d.ts +18 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +21 -0
- package/dist/audit.js.map +1 -0
- package/dist/auth.d.ts +31 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +69 -0
- package/dist/auth.js.map +1 -0
- package/dist/autogen/executor.d.ts +200 -0
- package/dist/autogen/executor.d.ts.map +1 -0
- package/dist/autogen/executor.js +277 -0
- package/dist/autogen/executor.js.map +1 -0
- package/dist/autogen/index.d.ts +18 -0
- package/dist/autogen/index.d.ts.map +1 -0
- package/dist/autogen/index.js +17 -0
- package/dist/autogen/index.js.map +1 -0
- package/dist/billing.d.ts +22 -0
- package/dist/billing.d.ts.map +1 -0
- package/dist/billing.js +33 -0
- package/dist/billing.js.map +1 -0
- package/dist/browser/encrypt.d.ts +68 -0
- package/dist/browser/encrypt.d.ts.map +1 -0
- package/dist/browser/encrypt.js +191 -0
- package/dist/browser/encrypt.js.map +1 -0
- package/dist/browser/index.d.ts +39 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +41 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/noble-provider.d.ts +10 -0
- package/dist/browser/noble-provider.d.ts.map +1 -0
- package/dist/browser/noble-provider.js +130 -0
- package/dist/browser/noble-provider.js.map +1 -0
- package/dist/browser/pqc-types.d.ts +40 -0
- package/dist/browser/pqc-types.d.ts.map +1 -0
- package/dist/browser/pqc-types.js +2 -0
- package/dist/browser/pqc-types.js.map +1 -0
- package/dist/browser/provider-setup.d.ts +70 -0
- package/dist/browser/provider-setup.d.ts.map +1 -0
- package/dist/browser/provider-setup.js +101 -0
- package/dist/browser/provider-setup.js.map +1 -0
- package/dist/browser/sdk-package-version.d.ts +12 -0
- package/dist/browser/sdk-package-version.d.ts.map +1 -0
- package/dist/browser/sdk-package-version.js +12 -0
- package/dist/browser/sdk-package-version.js.map +1 -0
- package/dist/browser/sign.d.ts +65 -0
- package/dist/browser/sign.d.ts.map +1 -0
- package/dist/browser/sign.js +124 -0
- package/dist/browser/sign.js.map +1 -0
- package/dist/browser/telemetry.d.ts +98 -0
- package/dist/browser/telemetry.d.ts.map +1 -0
- package/dist/browser/telemetry.js +93 -0
- package/dist/browser/telemetry.js.map +1 -0
- package/dist/cli/commands/access-control.d.ts +4 -0
- package/dist/cli/commands/access-control.d.ts.map +1 -0
- package/dist/cli/commands/access-control.js +183 -0
- package/dist/cli/commands/access-control.js.map +1 -0
- package/dist/cli/commands/audit.d.ts +4 -0
- package/dist/cli/commands/audit.d.ts.map +1 -0
- package/dist/cli/commands/audit.js +70 -0
- package/dist/cli/commands/audit.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +4 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +46 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/billing.d.ts +4 -0
- package/dist/cli/commands/billing.d.ts.map +1 -0
- package/dist/cli/commands/billing.js +179 -0
- package/dist/cli/commands/billing.js.map +1 -0
- package/dist/cli/commands/crypto-policy.d.ts +4 -0
- package/dist/cli/commands/crypto-policy.d.ts.map +1 -0
- package/dist/cli/commands/crypto-policy.js +130 -0
- package/dist/cli/commands/crypto-policy.js.map +1 -0
- package/dist/cli/commands/kms.d.ts +4 -0
- package/dist/cli/commands/kms.d.ts.map +1 -0
- package/dist/cli/commands/kms.js +153 -0
- package/dist/cli/commands/kms.js.map +1 -0
- package/dist/cli/commands/observability.d.ts +4 -0
- package/dist/cli/commands/observability.d.ts.map +1 -0
- package/dist/cli/commands/observability.js +97 -0
- package/dist/cli/commands/observability.js.map +1 -0
- package/dist/cli/commands/search.d.ts +4 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +66 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/commands/security.d.ts +4 -0
- package/dist/cli/commands/security.d.ts.map +1 -0
- package/dist/cli/commands/security.js +136 -0
- package/dist/cli/commands/security.js.map +1 -0
- package/dist/cli/commands/storage.d.ts +4 -0
- package/dist/cli/commands/storage.d.ts.map +1 -0
- package/dist/cli/commands/storage.js +85 -0
- package/dist/cli/commands/storage.js.map +1 -0
- package/dist/cli/commands/tenant.d.ts +4 -0
- package/dist/cli/commands/tenant.d.ts.map +1 -0
- package/dist/cli/commands/tenant.js +82 -0
- package/dist/cli/commands/tenant.js.map +1 -0
- package/dist/cli/commands/test-utils.d.ts +15 -0
- package/dist/cli/commands/test-utils.d.ts.map +1 -0
- package/dist/cli/commands/test-utils.js +72 -0
- package/dist/cli/commands/test-utils.js.map +1 -0
- package/dist/cli/commands/vault.d.ts +4 -0
- package/dist/cli/commands/vault.d.ts.map +1 -0
- package/dist/cli/commands/vault.js +111 -0
- package/dist/cli/commands/vault.js.map +1 -0
- package/dist/cli/config.d.ts +32 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +105 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +54 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils/audit-logger.d.ts +17 -0
- package/dist/cli/utils/audit-logger.d.ts.map +1 -0
- package/dist/cli/utils/audit-logger.js +52 -0
- package/dist/cli/utils/audit-logger.js.map +1 -0
- package/dist/cli/utils/auth.d.ts +4 -0
- package/dist/cli/utils/auth.d.ts.map +1 -0
- package/dist/cli/utils/auth.js +100 -0
- package/dist/cli/utils/auth.js.map +1 -0
- package/dist/cli/utils/backend-validator.d.ts +19 -0
- package/dist/cli/utils/backend-validator.d.ts.map +1 -0
- package/dist/cli/utils/backend-validator.js +72 -0
- package/dist/cli/utils/backend-validator.js.map +1 -0
- package/dist/cli/utils/command-config.d.ts +4 -0
- package/dist/cli/utils/command-config.d.ts.map +1 -0
- package/dist/cli/utils/command-config.js +29 -0
- package/dist/cli/utils/command-config.js.map +1 -0
- package/dist/cli/utils/fetcher.d.ts +3 -0
- package/dist/cli/utils/fetcher.d.ts.map +1 -0
- package/dist/cli/utils/fetcher.js +30 -0
- package/dist/cli/utils/fetcher.js.map +1 -0
- package/dist/cli/utils/https-validator.d.ts +9 -0
- package/dist/cli/utils/https-validator.d.ts.map +1 -0
- package/dist/cli/utils/https-validator.js +35 -0
- package/dist/cli/utils/https-validator.js.map +1 -0
- package/dist/cli/utils/output.d.ts +6 -0
- package/dist/cli/utils/output.d.ts.map +1 -0
- package/dist/cli/utils/output.js +29 -0
- package/dist/cli/utils/output.js.map +1 -0
- package/dist/cli/utils/pqc-validator.d.ts +17 -0
- package/dist/cli/utils/pqc-validator.d.ts.map +1 -0
- package/dist/cli/utils/pqc-validator.js +62 -0
- package/dist/cli/utils/pqc-validator.js.map +1 -0
- package/dist/cli/utils/prompt.d.ts +4 -0
- package/dist/cli/utils/prompt.d.ts.map +1 -0
- package/dist/cli/utils/prompt.js +30 -0
- package/dist/cli/utils/prompt.js.map +1 -0
- package/dist/cli/utils/rate-limiter.d.ts +15 -0
- package/dist/cli/utils/rate-limiter.d.ts.map +1 -0
- package/dist/cli/utils/rate-limiter.js +46 -0
- package/dist/cli/utils/rate-limiter.js.map +1 -0
- package/dist/cli/utils/sanitize.d.ts +3 -0
- package/dist/cli/utils/sanitize.d.ts.map +1 -0
- package/dist/cli/utils/sanitize.js +44 -0
- package/dist/cli/utils/sanitize.js.map +1 -0
- package/dist/cli/utils/security-headers.d.ts +18 -0
- package/dist/cli/utils/security-headers.d.ts.map +1 -0
- package/dist/cli/utils/security-headers.js +32 -0
- package/dist/cli/utils/security-headers.js.map +1 -0
- package/dist/cli/utils/token-cache.d.ts +4 -0
- package/dist/cli/utils/token-cache.d.ts.map +1 -0
- package/dist/cli/utils/token-cache.js +22 -0
- package/dist/cli/utils/token-cache.js.map +1 -0
- package/dist/client.d.ts +52 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +78 -0
- package/dist/client.js.map +1 -0
- package/dist/crypto-inventory.d.ts +21 -0
- package/dist/crypto-inventory.d.ts.map +1 -0
- package/dist/crypto-inventory.js +28 -0
- package/dist/crypto-inventory.js.map +1 -0
- package/dist/errors.d.ts +35 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +64 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/kms.d.ts +30 -0
- package/dist/kms.d.ts.map +1 -0
- package/dist/kms.js +92 -0
- package/dist/kms.js.map +1 -0
- package/dist/langchain/index.d.ts +22 -0
- package/dist/langchain/index.d.ts.map +1 -0
- package/dist/langchain/index.js +23 -0
- package/dist/langchain/index.js.map +1 -0
- package/dist/langchain/toolkit.d.ts +85 -0
- package/dist/langchain/toolkit.d.ts.map +1 -0
- package/dist/langchain/toolkit.js +146 -0
- package/dist/langchain/toolkit.js.map +1 -0
- package/dist/langchain/tools/audit.d.ts +43 -0
- package/dist/langchain/tools/audit.d.ts.map +1 -0
- package/dist/langchain/tools/audit.js +78 -0
- package/dist/langchain/tools/audit.js.map +1 -0
- package/dist/langchain/tools/kms.d.ts +62 -0
- package/dist/langchain/tools/kms.d.ts.map +1 -0
- package/dist/langchain/tools/kms.js +120 -0
- package/dist/langchain/tools/kms.js.map +1 -0
- package/dist/langchain/tools/vault.d.ts +69 -0
- package/dist/langchain/tools/vault.d.ts.map +1 -0
- package/dist/langchain/tools/vault.js +107 -0
- package/dist/langchain/tools/vault.js.map +1 -0
- package/dist/langchain/vault-client.d.ts +82 -0
- package/dist/langchain/vault-client.d.ts.map +1 -0
- package/dist/langchain/vault-client.js +133 -0
- package/dist/langchain/vault-client.js.map +1 -0
- package/dist/llamaindex/index.d.ts +16 -0
- package/dist/llamaindex/index.d.ts.map +1 -0
- package/dist/llamaindex/index.js +15 -0
- package/dist/llamaindex/index.js.map +1 -0
- package/dist/llamaindex/sse.d.ts +36 -0
- package/dist/llamaindex/sse.d.ts.map +1 -0
- package/dist/llamaindex/sse.js +151 -0
- package/dist/llamaindex/sse.js.map +1 -0
- package/dist/llamaindex/vector-store.d.ts +101 -0
- package/dist/llamaindex/vector-store.d.ts.map +1 -0
- package/dist/llamaindex/vector-store.js +348 -0
- package/dist/llamaindex/vector-store.js.map +1 -0
- package/dist/search.d.ts +32 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +27 -0
- package/dist/search.js.map +1 -0
- package/dist/storage.d.ts +32 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +58 -0
- package/dist/storage.js.map +1 -0
- package/dist/tenant.d.ts +25 -0
- package/dist/tenant.d.ts.map +1 -0
- package/dist/tenant.js +36 -0
- package/dist/tenant.js.map +1 -0
- package/dist/vault.d.ts +22 -0
- package/dist/vault.d.ts.map +1 -0
- package/dist/vault.js +43 -0
- package/dist/vault.js.map +1 -0
- package/dist/webhooks.d.ts +32 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +77 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +118 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# @heossi/qnsi
|
|
2
|
+
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Framework-adapter consolidation: the former standalone satellites
|
|
8
|
+
`@heossi/qnsi-browser`, `-langchain-qnsp`, `-llamaindex-qnsp`, and
|
|
9
|
+
`-autogen-qnsp` are folded in as subpaths of the one SDK —
|
|
10
|
+
`@heossi/qnsi/browser` (client-side PQC encryption/signing via
|
|
11
|
+
`@noble/post-quantum`), `@heossi/qnsi/langchain` (governed-agent
|
|
12
|
+
toolkit), `@heossi/qnsi/llamaindex` (SSE-X encrypted vector store), and
|
|
13
|
+
`@heossi/qnsi/autogen` (enclave code executor). Each subpath is
|
|
14
|
+
self-contained (no internal `@heossi/qnsi-*` workspace deps) and
|
|
15
|
+
preserves the prior behavior, endpoints, SSE-X token crypto, and
|
|
16
|
+
activation `sdkId`s byte-for-byte. Framework integrations
|
|
17
|
+
(`@langchain/core`, `llamaindex`, `autogen`) are **optional**
|
|
18
|
+
`peerDependencies`; `@noble/hashes`/`@noble/post-quantum` are runtime
|
|
19
|
+
deps for the browser + llamaindex SSE-X paths. The four standalone
|
|
20
|
+
packages are deleted (they were never published). Non-breaking: the
|
|
21
|
+
root export and `@heossi/qnsi/activation` are unchanged.
|
|
22
|
+
|
|
23
|
+
## 0.2.0
|
|
24
|
+
|
|
25
|
+
### Minor Changes
|
|
26
|
+
|
|
27
|
+
- Single-SDK consolidation: completes the `@qnsp` → `@heossi/qnsi` scope
|
|
28
|
+
migration, folds the CLI in as the `qnsp` bin, and exposes the inlined
|
|
29
|
+
activation client as the `@heossi/qnsi/activation` subpath. The retired
|
|
30
|
+
standalone satellites (`-cli`, `-browser`, `-sdk-activation`,
|
|
31
|
+
`-langchain-qnsp`, `-llamaindex-qnsp`, `-autogen-qnsp`) are unpublished;
|
|
32
|
+
`@heossi/qnsi` is the one SDK to install.
|
|
33
|
+
|
|
34
|
+
## 0.1.0 — 2026-04-30
|
|
35
|
+
|
|
36
|
+
**Initial release.** The single-package Node.js / TypeScript SDK for QNSP, replacing the 11 per-service `@heossi/qnsi-*-sdk` packages with one consolidated entry point.
|
|
37
|
+
|
|
38
|
+
### Why this exists
|
|
39
|
+
|
|
40
|
+
The previous TypeScript SDK family was fragmented across 11 packages (`@heossi/qnsi-vault-sdk`, `@heossi/qnsi-kms-client`, `@heossi/qnsi-audit-sdk`, `@heossi/qnsi-auth-sdk`, `@heossi/qnsi-tenant-sdk`, `@heossi/qnsi-access-control-sdk`, `@heossi/qnsi-billing-sdk`, `@heossi/qnsi-crypto-inventory-sdk`, `@heossi/qnsi-storage-sdk`, `@heossi/qnsi-search-sdk`, `@heossi/qnsi-ai-sdk`). Each ran its own activation handshake, kept its own version, owned its own CHANGELOG, and emitted its own activation telemetry — making it hard to answer simple questions like "did this developer's SDK reach our backend?" or "which SDK install tripped the activation gate?".
|
|
41
|
+
|
|
42
|
+
`@heossi/qnsi` collapses that into one package with eleven sub-namespaces, mirroring the `qnsp` Python / Go / Rust SDK shape. One activation, one connection pool, one CHANGELOG, one source of truth — same diagnostic surface as the other-language SDKs.
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- `QnspClient({ apiKey, baseUrl?, timeoutMs? })` — top-level client. Lazily activates against `/billing/v1/sdk/activate` on first request, reports `sdkId="qnsp"` and `sdkVersion="0.1.0"`.
|
|
47
|
+
- Eleven service sub-clients sharing one HTTP pool + one activation cache:
|
|
48
|
+
- `qnsp.vault` (createSecret / getSecret / getSecretVersion / rotateSecret / deleteSecret / listSecretVersions)
|
|
49
|
+
- `qnsp.kms` (createKey / listKeys / getKey / rotateKey / deleteKey / sign / verify / wrap / unwrap)
|
|
50
|
+
- `qnsp.audit` (logEvent / ingestEvents / listEvents)
|
|
51
|
+
- `qnsp.auth` (login / refreshToken / revoke / WebAuthn passkey lifecycle / MFA / SAML / OIDC / risk-based auth)
|
|
52
|
+
- `qnsp.tenant` (CRUD / crypto-policy management / quota / health)
|
|
53
|
+
- `qnsp.access` (RBAC roles, role assignments, checkPermission)
|
|
54
|
+
- `qnsp.billing` (entitlements, usage meters, invoices, credit balance)
|
|
55
|
+
- `qnsp.cryptoInventory` (CBOM: assets, discovery runs, PQC readiness)
|
|
56
|
+
- `qnsp.storage` (PQC-encrypted object storage with SSE-X)
|
|
57
|
+
- `qnsp.search` (encrypted vector search)
|
|
58
|
+
- `qnsp.ai` (model registry, workloads, inference, artifacts)
|
|
59
|
+
- `parseQnspWebhook` and `verifyQnspWebhookSignature` — HMAC-SHA-256 verification + replay protection, identical to the helpers in the Python / Go / Rust SDKs.
|
|
60
|
+
- Typed error hierarchy: `QnspError`, `QnspNetworkError`, `QnspAuthError`, `QnspApiError`, `QnspWebhookError`.
|
|
61
|
+
- Top-level introspection: `tenantId()`, `tier()`, `limits()`, `hasFeature(name)`, `ensureActivated()`.
|
|
62
|
+
|
|
63
|
+
### Migration
|
|
64
|
+
|
|
65
|
+
The 11 per-service `@heossi/qnsi-*-sdk` packages on npm are now `npm deprecate`d to point at `@heossi/qnsi`. Existing installs continue to work; new code should reach for `@heossi/qnsi` directly. See the [Migration section in the README](./README.md#migration-from-per-service-sdks) for the import-by-import mapping.
|
|
66
|
+
|
|
67
|
+
The internal QNSP monorepo continues to use the per-service packages for service-to-service calls; that migration will happen in a separate wave and is invisible to external consumers.
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# QNSP Licensing
|
|
2
|
+
|
|
3
|
+
This repository is **multi-licensed**.
|
|
4
|
+
|
|
5
|
+
- Source code under `packages/*` and selected `apps/*` directories is licensed **per package**. Refer to the `LICENSE` file inside each package directory.
|
|
6
|
+
- Public SDK packages (those with `publishConfig.access: "public"`) are licensed under the **Apache License 2.0**.
|
|
7
|
+
- Core platform packages (including `apps/ai-orchestrator` and `packages/kms`, and `packages/liboqs-native`) are licensed under the **Business Source License 1.1** with a Change License of **GPL-2.0-or-later**.
|
|
8
|
+
- Materials under `docs/patent-ip-candidates` are **Proprietary**.
|
package/README.md
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# @heossi/qnsi — Node.js / TypeScript SDK for the Quantum-Native Security Infrastructure
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@heossi/qnsi)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
6
|
+
The official **single-package** Node.js / TypeScript SDK for QNSI. Covers the full customer-facing platform — vault, KMS, audit, auth, tenant, access-control, billing, crypto-inventory, storage, search, and AI orchestrator — plus webhook signature verification. Mirrors the shape of the `qnsp` Python / Go / Rust SDKs byte-for-byte: same wire contracts, same algorithm names, same FIPS 203 / 204 / 205 posture.
|
|
7
|
+
|
|
8
|
+
> **Free tier available.** Free-forever account at <https://cloud.qnsp.cuilabs.io/auth> — 60-second signup, no credit card. Includes 10 GB PQC storage, 50 000 API calls/month, 20 KMS keys, 25 vault secrets.
|
|
9
|
+
|
|
10
|
+
## Why one package?
|
|
11
|
+
|
|
12
|
+
Previous TypeScript consumers had to install up to 11 separate `@heossi/qnsi-*-sdk` packages and keep their versions in sync. `@heossi/qnsi` collapses that into a single dependency with sub-namespaces:
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { QnspClient } from "@heossi/qnsi";
|
|
16
|
+
|
|
17
|
+
const qnsp = new QnspClient({ apiKey: process.env.QNSP_API_KEY! });
|
|
18
|
+
|
|
19
|
+
await qnsp.vault.createSecret({ ... }); // was @heossi/qnsi-vault-sdk
|
|
20
|
+
await qnsp.kms.sign(keyId, data); // was @heossi/qnsi-kms-client
|
|
21
|
+
await qnsp.audit.logEvent({ ... }); // was @heossi/qnsi-audit-sdk
|
|
22
|
+
await qnsp.tenant.getTenant(tenantId); // was @heossi/qnsi-tenant-sdk
|
|
23
|
+
// ...
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
One activation handshake on first use, shared across all 11 sub-clients. One version bump per QNSI release. One CHANGELOG. One source of truth.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pnpm add @heossi/qnsi
|
|
32
|
+
# or
|
|
33
|
+
npm install @heossi/qnsi
|
|
34
|
+
# or
|
|
35
|
+
yarn add @heossi/qnsi
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Requires Node.js ≥ 22.0.0. ESM-first; CommonJS consumers can `await import("@heossi/qnsi")`.
|
|
39
|
+
|
|
40
|
+
## Quick start
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { QnspClient } from "@heossi/qnsi";
|
|
44
|
+
|
|
45
|
+
const qnsp = new QnspClient({ apiKey: process.env.QNSP_API_KEY! });
|
|
46
|
+
|
|
47
|
+
// Vault — PQC-encrypted secret storage
|
|
48
|
+
const secret = await qnsp.vault.createSecret({
|
|
49
|
+
name: "openai-api-key",
|
|
50
|
+
payloadB64: Buffer.from("sk-...").toString("base64"),
|
|
51
|
+
algorithm: "ml-kem-768",
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// KMS — server-side PQC keys
|
|
55
|
+
const key = await qnsp.kms.createKey({ algorithm: "ml-dsa-65", purpose: "signing" });
|
|
56
|
+
const sig = await qnsp.kms.sign(key.keyId as string, new TextEncoder().encode("hello"));
|
|
57
|
+
const ok = await qnsp.kms.verify(key.keyId as string, new TextEncoder().encode("hello"), sig);
|
|
58
|
+
|
|
59
|
+
// Audit — immutable, hash-chained event log
|
|
60
|
+
await qnsp.audit.logEvent({
|
|
61
|
+
eventType: "model.inference",
|
|
62
|
+
payload: { modelId: "gpt-4o", latencyMs: 412 },
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Tenant, access, billing, crypto-inventory, storage, search, ai, auth — all on one client
|
|
66
|
+
await qnsp.tenant.getTenant(await qnsp.tenantId());
|
|
67
|
+
await qnsp.access.checkPermission({ subjectId: "user-1", permission: "vault.read" });
|
|
68
|
+
await qnsp.billing.getEntitlements();
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Modules
|
|
72
|
+
|
|
73
|
+
Each sub-namespace wraps one QNSI backend service:
|
|
74
|
+
|
|
75
|
+
| Sub-client | Wraps | Key methods |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| `qnsp.vault` | `apps/vault-service` (`/vault/v1`) | `createSecret`, `getSecret`, `getSecretVersion`, `rotateSecret`, `deleteSecret`, `listSecretVersions` |
|
|
78
|
+
| `qnsp.kms` | `apps/kms-service` (`/kms/v1`) | `createKey`, `listKeys`, `getKey`, `rotateKey`, `deleteKey`, `sign`, `verify`, `wrap`, `unwrap` |
|
|
79
|
+
| `qnsp.audit` | `apps/audit-service` (`/audit/v1`) | `logEvent`, `ingestEvents`, `listEvents` |
|
|
80
|
+
| `qnsp.auth` | `apps/auth-service` (`/auth/v1`) | `login`, `refreshToken`, `revoke`, WebAuthn passkey lifecycle, `mfaChallenge` / `mfaVerify`, `federateSAML` / `federateOIDC`, `evaluateRisk` |
|
|
81
|
+
| `qnsp.tenant` | `apps/tenant-service` (`/tenant/v1`) | `createTenant`, `getTenant`, `updateTenant`, `listTenants`, `getCryptoPolicy`, `upsertCryptoPolicy`, `getCurrentHealth`, `getCurrentQuotas` |
|
|
82
|
+
| `qnsp.access` | `apps/access-control-service` (`/access/v1`) | `createRole`, `getRole`, `listRoles`, `deleteRole`, `assignRole`, `revokeRoleAssignment`, `checkPermission` |
|
|
83
|
+
| `qnsp.billing` | `apps/billing-service` (`/billing/v1`) | `getEntitlements`, `ingestMeter`, `ingestMeters`, `listInvoices`, `getInvoice`, `getCreditBalance` |
|
|
84
|
+
| `qnsp.cryptoInventory` | `apps/crypto-inventory-service` (`/crypto/v1`) | `listAssets`, `getAsset`, `getAssetStats`, `discoverAssets`, `getReadinessScore` |
|
|
85
|
+
| `qnsp.storage` | `apps/storage-service` (`/storage/storage/v1`) | `putObject`, `getObject` (returns `[bytes, descriptor]`), `deleteObject`, `listObjects`, `listBuckets` |
|
|
86
|
+
| `qnsp.search` | `apps/search-service` (`/search/v1`) | `createIndex`, `listIndexes`, `deleteIndex`, `upsertVectors`, `query` |
|
|
87
|
+
| `qnsp.ai` | `apps/ai-orchestrator` (`/ai/v1`) | model registry (`registerModel`, `listModels`, `getModel`, `updateModel`, `activateModel`, `deployModel`), workloads (`submitWorkload`, `getWorkload`, `listWorkloads`, `cancelWorkload`), `invokeInference`, `registerArtifact` |
|
|
88
|
+
|
|
89
|
+
## Verifying inbound webhooks
|
|
90
|
+
|
|
91
|
+
QNSI signs every webhook with HMAC-SHA-256. Verify the **raw body** before parsing JSON:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import { parseQnspWebhook, QnspWebhookError } from "@heossi/qnsi";
|
|
95
|
+
|
|
96
|
+
app.post("/webhooks/qnsp", express.raw({ type: "application/json" }), (req, res) => {
|
|
97
|
+
try {
|
|
98
|
+
const event = parseQnspWebhook({
|
|
99
|
+
body: req.body, // raw Buffer
|
|
100
|
+
signatureHeader: req.header("x-qnsp-signature") ?? "",
|
|
101
|
+
timestampHeader: req.header("x-qnsp-timestamp"),
|
|
102
|
+
secret: process.env.QNSP_WEBHOOK_SECRET!,
|
|
103
|
+
});
|
|
104
|
+
if (event.eventType === "key.rotated") {
|
|
105
|
+
// ...
|
|
106
|
+
}
|
|
107
|
+
res.sendStatus(200);
|
|
108
|
+
} catch (err) {
|
|
109
|
+
if (err instanceof QnspWebhookError) {
|
|
110
|
+
res.status(400).send(err.reason);
|
|
111
|
+
} else {
|
|
112
|
+
throw err;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Constant-time HMAC comparison, 5-minute replay window by default (`MAX_WEBHOOK_SKEW_MS`), refuses payloads missing required fields.
|
|
119
|
+
|
|
120
|
+
## Error handling
|
|
121
|
+
|
|
122
|
+
All errors descend from `QnspError`:
|
|
123
|
+
|
|
124
|
+
| Class | When |
|
|
125
|
+
|---|---|
|
|
126
|
+
| `QnspNetworkError` | DNS, TLS, timeout, or connection failure |
|
|
127
|
+
| `QnspAuthError` | API key rejected at activation |
|
|
128
|
+
| `QnspApiError` | A service returned 4xx/5xx with a structured body |
|
|
129
|
+
| `QnspWebhookError` | HMAC mismatch, expired timestamp, malformed body, etc. |
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { QnspApiError, QnspNetworkError } from "@heossi/qnsi";
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
await qnsp.vault.getSecret("missing");
|
|
136
|
+
} catch (err) {
|
|
137
|
+
if (err instanceof QnspApiError) console.log("HTTP", err.statusCode, err.code);
|
|
138
|
+
else if (err instanceof QnspNetworkError) console.log("could not reach QNSI:", err.message);
|
|
139
|
+
else throw err;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Activation + tier introspection
|
|
144
|
+
|
|
145
|
+
`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 ~60 s before expiry. You can inspect the current activation:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
await qnsp.tenantId(); // resolved tenant
|
|
149
|
+
await qnsp.tier(); // plan tier
|
|
150
|
+
await qnsp.limits(); // full limits dict
|
|
151
|
+
await qnsp.hasFeature("sseEnabled"); // convenience boolean
|
|
152
|
+
|
|
153
|
+
// Force the handshake at startup so you fail fast on a bad key:
|
|
154
|
+
await qnsp.ensureActivated();
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
If the activation token is rotated server-side, the SDK invalidates its cache and retries the originating request once on a 401.
|
|
158
|
+
|
|
159
|
+
## Migration from per-service SDKs
|
|
160
|
+
|
|
161
|
+
The per-service `@heossi/qnsi-*-sdk` packages on npm are now **deprecated** in favour of `@heossi/qnsi`. They continue to install and work, but new code should use this package.
|
|
162
|
+
|
|
163
|
+
| Before | After |
|
|
164
|
+
|---|---|
|
|
165
|
+
| `import { VaultClient } from "@heossi/qnsi-vault-sdk"` | `import { QnspClient } from "@heossi/qnsi"` then `qnsp.vault` |
|
|
166
|
+
| `import { KmsClient } from "@heossi/qnsi-kms-client"` | `qnsp.kms` |
|
|
167
|
+
| `import { AuthClient } from "@heossi/qnsi-auth-sdk"` | `qnsp.auth` |
|
|
168
|
+
| `import { TenantClient } from "@heossi/qnsi-tenant-sdk"` | `qnsp.tenant` |
|
|
169
|
+
| `import { AccessControlClient } from "@heossi/qnsi-access-control-sdk"` | `qnsp.access` |
|
|
170
|
+
| `import { BillingClient } from "@heossi/qnsi-billing-sdk"` | `qnsp.billing` |
|
|
171
|
+
| `import { CryptoInventoryClient } from "@heossi/qnsi-crypto-inventory-sdk"` | `qnsp.cryptoInventory` |
|
|
172
|
+
| `import { StorageClient } from "@heossi/qnsi-storage-sdk"` | `qnsp.storage` |
|
|
173
|
+
| `import { SearchClient } from "@heossi/qnsi-search-sdk"` | `qnsp.search` |
|
|
174
|
+
| `import { AiOrchestratorClient } from "@heossi/qnsi-ai-sdk"` | `qnsp.ai` |
|
|
175
|
+
| `import { AuditClient } from "@heossi/qnsi-audit-sdk"` | `qnsp.audit` |
|
|
176
|
+
|
|
177
|
+
The constructor signature is simpler — one `apiKey` for everything, instead of a per-service config:
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
// Before — 11 packages, 11 activation handshakes, 11 versions to keep in sync
|
|
181
|
+
import { VaultClient } from "@heossi/qnsi-vault-sdk";
|
|
182
|
+
import { KmsClient } from "@heossi/qnsi-kms-client";
|
|
183
|
+
import { AuditClient } from "@heossi/qnsi-audit-sdk";
|
|
184
|
+
|
|
185
|
+
const vault = new VaultClient({ apiKey, baseUrl: "https://api.qnsp.cuilabs.io/proxy/vault", tier });
|
|
186
|
+
const kms = new KmsClient({ apiKey, baseUrl: "https://api.qnsp.cuilabs.io/proxy/kms", tier });
|
|
187
|
+
const audit = new AuditClient({ apiKey, baseUrl: "https://api.qnsp.cuilabs.io/proxy/audit", tier });
|
|
188
|
+
|
|
189
|
+
// After — one package, one activation, one client
|
|
190
|
+
import { QnspClient } from "@heossi/qnsi";
|
|
191
|
+
|
|
192
|
+
const qnsp = new QnspClient({ apiKey });
|
|
193
|
+
// qnsp.vault, qnsp.kms, qnsp.audit, ... all share one connection pool + one activation cache
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The wire contracts are identical, so migrating method-by-method is mechanical.
|
|
197
|
+
|
|
198
|
+
## License
|
|
199
|
+
|
|
200
|
+
Apache-2.0. See [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Activation Client
|
|
3
|
+
*
|
|
4
|
+
* Handles activation handshake with the QNSP billing-service.
|
|
5
|
+
* Browser-compatible — uses global fetch, no node: imports.
|
|
6
|
+
*
|
|
7
|
+
* Every SDK must call `activateSdk()` before performing operations.
|
|
8
|
+
* The activation validates the API key against the QNSP backend,
|
|
9
|
+
* returns tier limits, and issues a short-lived activation token.
|
|
10
|
+
*
|
|
11
|
+
* Activation tokens are cached in-memory and auto-refreshed before expiry.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import { type SdkActivationError, type SdkActivationLimits, type SdkActivationResponse, type SdkIdentifier } from "./types.js";
|
|
16
|
+
/**
|
|
17
|
+
* Typed error for SDK activation failures.
|
|
18
|
+
*/
|
|
19
|
+
export declare class SdkActivationError_ extends Error {
|
|
20
|
+
readonly code: SdkActivationError["code"];
|
|
21
|
+
readonly statusCode: number;
|
|
22
|
+
constructor(code: SdkActivationError["code"], message: string, statusCode: number);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Configuration for SDK activation.
|
|
26
|
+
*/
|
|
27
|
+
export interface SdkActivationConfig {
|
|
28
|
+
/** QNSP API key (required — get one at https://cloud.qnsp.cuilabs.io/signup) */
|
|
29
|
+
readonly apiKey: string;
|
|
30
|
+
/** SDK package identifier */
|
|
31
|
+
readonly sdkId: SdkIdentifier;
|
|
32
|
+
/** SDK version string */
|
|
33
|
+
readonly sdkVersion: string;
|
|
34
|
+
/** Override platform URL (defaults to https://api.qnsp.cuilabs.io) */
|
|
35
|
+
readonly platformUrl?: string | undefined;
|
|
36
|
+
/** Override activation timeout in ms (defaults to 15000) */
|
|
37
|
+
readonly timeoutMs?: number | undefined;
|
|
38
|
+
/** Custom fetch implementation (for testing or non-standard runtimes) */
|
|
39
|
+
readonly fetchImpl?: (typeof globalThis)["fetch"] | undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Activate an SDK against the QNSP platform.
|
|
43
|
+
*
|
|
44
|
+
* This must be called before any SDK operations. It validates the API key,
|
|
45
|
+
* returns the tenant's tier and limits, and caches the activation token.
|
|
46
|
+
*
|
|
47
|
+
* Cached activations are returned immediately if still valid.
|
|
48
|
+
* Tokens are auto-refreshed 5 minutes before expiry.
|
|
49
|
+
*
|
|
50
|
+
* @throws {SdkActivationError_} if the API key is invalid, account is suspended, or service is unavailable
|
|
51
|
+
*/
|
|
52
|
+
export declare function activateSdk(config: SdkActivationConfig): Promise<SdkActivationResponse>;
|
|
53
|
+
/**
|
|
54
|
+
* Get the cached activation for an SDK, or null if not activated.
|
|
55
|
+
*/
|
|
56
|
+
export declare function getCachedActivation(config: SdkActivationConfig): SdkActivationResponse | null;
|
|
57
|
+
/**
|
|
58
|
+
* Get the tier limits from a cached activation.
|
|
59
|
+
*/
|
|
60
|
+
export declare function getActivationLimits(config: SdkActivationConfig): SdkActivationLimits | null;
|
|
61
|
+
/**
|
|
62
|
+
* Clear all cached activations. Primarily for testing.
|
|
63
|
+
*/
|
|
64
|
+
export declare function clearActivationCache(): void;
|
|
65
|
+
//# sourceMappingURL=activation-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activation-client.d.ts","sourceRoot":"","sources":["../../src/_activation/activation-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACN,KAAK,kBAAkB,EAEvB,KAAK,mBAAmB,EAExB,KAAK,qBAAqB,EAE1B,KAAK,aAAa,EAClB,MAAM,YAAY,CAAC;AAOpB;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAMjF;AAUD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,yBAAyB;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,yEAAyE;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;CAC9D;AAsBD;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA+G7F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,qBAAqB,GAAG,IAAI,CAS7F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,mBAAmB,GAAG,IAAI,CAG3F;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Activation Client
|
|
3
|
+
*
|
|
4
|
+
* Handles activation handshake with the QNSP billing-service.
|
|
5
|
+
* Browser-compatible — uses global fetch, no node: imports.
|
|
6
|
+
*
|
|
7
|
+
* Every SDK must call `activateSdk()` before performing operations.
|
|
8
|
+
* The activation validates the API key against the QNSP backend,
|
|
9
|
+
* returns tier limits, and issues a short-lived activation token.
|
|
10
|
+
*
|
|
11
|
+
* Activation tokens are cached in-memory and auto-refreshed before expiry.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import { SdkActivationErrorSchema, SdkActivationResponseSchema, } from "./types.js";
|
|
16
|
+
const ACTIVATION_PATH = "/billing/v1/sdk/activate";
|
|
17
|
+
const DEFAULT_PLATFORM_URL = "https://api.qnsp.cuilabs.io";
|
|
18
|
+
const ACTIVATION_TIMEOUT_MS = 15_000;
|
|
19
|
+
const REFRESH_BUFFER_SECONDS = 300; // Refresh 5 minutes before expiry
|
|
20
|
+
/**
|
|
21
|
+
* Typed error for SDK activation failures.
|
|
22
|
+
*/
|
|
23
|
+
export class SdkActivationError_ extends Error {
|
|
24
|
+
code;
|
|
25
|
+
statusCode;
|
|
26
|
+
constructor(code, message, statusCode) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "SdkActivationError";
|
|
29
|
+
this.code = code;
|
|
30
|
+
this.statusCode = statusCode;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** In-memory activation cache keyed by `${platformUrl}:${apiKeyPrefix}:${sdkId}` */
|
|
34
|
+
const activationCache = new Map();
|
|
35
|
+
function cacheKey(config) {
|
|
36
|
+
const url = config.platformUrl ?? DEFAULT_PLATFORM_URL;
|
|
37
|
+
// Use first 8 chars of API key for cache key (avoid storing full key in memory map keys)
|
|
38
|
+
const keyPrefix = config.apiKey.slice(0, 8);
|
|
39
|
+
return `${url}:${keyPrefix}:${config.sdkId}`;
|
|
40
|
+
}
|
|
41
|
+
function detectRuntime() {
|
|
42
|
+
if (typeof globalThis.process !== "undefined" && globalThis.process.versions?.node) {
|
|
43
|
+
return "node";
|
|
44
|
+
}
|
|
45
|
+
if ("window" in globalThis && "document" in globalThis) {
|
|
46
|
+
return "browser";
|
|
47
|
+
}
|
|
48
|
+
return "edge";
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Activate an SDK against the QNSP platform.
|
|
52
|
+
*
|
|
53
|
+
* This must be called before any SDK operations. It validates the API key,
|
|
54
|
+
* returns the tenant's tier and limits, and caches the activation token.
|
|
55
|
+
*
|
|
56
|
+
* Cached activations are returned immediately if still valid.
|
|
57
|
+
* Tokens are auto-refreshed 5 minutes before expiry.
|
|
58
|
+
*
|
|
59
|
+
* @throws {SdkActivationError_} if the API key is invalid, account is suspended, or service is unavailable
|
|
60
|
+
*/
|
|
61
|
+
export async function activateSdk(config) {
|
|
62
|
+
if (!config.apiKey || config.apiKey.trim().length === 0) {
|
|
63
|
+
throw new SdkActivationError_("INVALID_API_KEY", `QNSP ${config.sdkId}: apiKey is required. ` +
|
|
64
|
+
"Get your free API key at https://cloud.qnsp.cuilabs.io/signup — " +
|
|
65
|
+
"no credit card required (FREE tier: 10 GB storage, 50,000 API calls/month). " +
|
|
66
|
+
`Docs: https://docs.qnsp.cuilabs.io/sdk/${config.sdkId}`, 401);
|
|
67
|
+
}
|
|
68
|
+
const key = cacheKey(config);
|
|
69
|
+
const cached = activationCache.get(key);
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
// Return cached activation if still valid (with refresh buffer)
|
|
72
|
+
if (cached && cached.expiresAt - REFRESH_BUFFER_SECONDS * 1000 > now) {
|
|
73
|
+
return cached.response;
|
|
74
|
+
}
|
|
75
|
+
const platformUrl = (config.platformUrl ?? DEFAULT_PLATFORM_URL).replace(/\/$/, "");
|
|
76
|
+
const timeoutMs = config.timeoutMs ?? ACTIVATION_TIMEOUT_MS;
|
|
77
|
+
const fetchFn = config.fetchImpl ?? globalThis.fetch;
|
|
78
|
+
const body = {
|
|
79
|
+
sdkId: config.sdkId,
|
|
80
|
+
sdkVersion: config.sdkVersion,
|
|
81
|
+
runtime: detectRuntime(),
|
|
82
|
+
};
|
|
83
|
+
let response;
|
|
84
|
+
try {
|
|
85
|
+
response = await fetchFn(`${platformUrl}${ACTIVATION_PATH}`, {
|
|
86
|
+
method: "POST",
|
|
87
|
+
headers: {
|
|
88
|
+
"content-type": "application/json",
|
|
89
|
+
authorization: `Bearer ${config.apiKey}`,
|
|
90
|
+
},
|
|
91
|
+
body: JSON.stringify(body),
|
|
92
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (cause) {
|
|
96
|
+
throw new SdkActivationError_("SERVICE_UNAVAILABLE", `QNSP ${config.sdkId}: Failed to reach QNSP platform for activation. ` +
|
|
97
|
+
`Ensure network connectivity to ${platformUrl}. ` +
|
|
98
|
+
`Error: ${cause instanceof Error ? cause.message : String(cause)}`, 503);
|
|
99
|
+
}
|
|
100
|
+
if (!response.ok) {
|
|
101
|
+
let errorBody;
|
|
102
|
+
try {
|
|
103
|
+
const json = await response.json();
|
|
104
|
+
const parsed = SdkActivationErrorSchema.safeParse(json);
|
|
105
|
+
if (parsed.success) {
|
|
106
|
+
errorBody = parsed.data;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Ignore JSON parse errors — use status code
|
|
111
|
+
}
|
|
112
|
+
if (errorBody) {
|
|
113
|
+
throw new SdkActivationError_(errorBody.code, errorBody.error, response.status);
|
|
114
|
+
}
|
|
115
|
+
if (response.status === 401) {
|
|
116
|
+
throw new SdkActivationError_("INVALID_API_KEY", `QNSP ${config.sdkId}: Invalid API key. ` +
|
|
117
|
+
"Get your API key at https://cloud.qnsp.cuilabs.io/api-keys", 401);
|
|
118
|
+
}
|
|
119
|
+
if (response.status === 429) {
|
|
120
|
+
throw new SdkActivationError_("RATE_LIMITED", `QNSP ${config.sdkId}: Activation rate limited. Please retry after a short delay.`, 429);
|
|
121
|
+
}
|
|
122
|
+
throw new SdkActivationError_("SERVICE_UNAVAILABLE", `QNSP ${config.sdkId}: Activation failed with HTTP ${response.status}`, response.status);
|
|
123
|
+
}
|
|
124
|
+
const json = await response.json();
|
|
125
|
+
const parsed = SdkActivationResponseSchema.safeParse(json);
|
|
126
|
+
if (!parsed.success) {
|
|
127
|
+
throw new SdkActivationError_("SERVICE_UNAVAILABLE", `QNSP ${config.sdkId}: Invalid activation response from platform`, 502);
|
|
128
|
+
}
|
|
129
|
+
const activation = parsed.data;
|
|
130
|
+
// Cache the activation
|
|
131
|
+
activationCache.set(key, {
|
|
132
|
+
response: activation,
|
|
133
|
+
expiresAt: now + activation.expiresInSeconds * 1000,
|
|
134
|
+
});
|
|
135
|
+
return activation;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get the cached activation for an SDK, or null if not activated.
|
|
139
|
+
*/
|
|
140
|
+
export function getCachedActivation(config) {
|
|
141
|
+
const key = cacheKey(config);
|
|
142
|
+
const cached = activationCache.get(key);
|
|
143
|
+
if (!cached)
|
|
144
|
+
return null;
|
|
145
|
+
if (cached.expiresAt < Date.now()) {
|
|
146
|
+
activationCache.delete(key);
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
return cached.response;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get the tier limits from a cached activation.
|
|
153
|
+
*/
|
|
154
|
+
export function getActivationLimits(config) {
|
|
155
|
+
const activation = getCachedActivation(config);
|
|
156
|
+
return activation?.limits ?? null;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Clear all cached activations. Primarily for testing.
|
|
160
|
+
*/
|
|
161
|
+
export function clearActivationCache() {
|
|
162
|
+
activationCache.clear();
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=activation-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activation-client.js","sourceRoot":"","sources":["../../src/_activation/activation-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inlined copy of @heossi/qnsi-sdk-activation (workspace package, not published).
|
|
3
|
+
* Bundled here so @heossi/qnsi has no external @heossi/qnsi-* dependencies.
|
|
4
|
+
* Keep this folder in sync with packages/sdk-activation/src/ when changes
|
|
5
|
+
* land upstream — both files are minimal (activation-client.ts +
|
|
6
|
+
* types.ts) so a manual diff is tractable.
|
|
7
|
+
*/
|
|
8
|
+
export { activateSdk, clearActivationCache, getActivationLimits, getCachedActivation, type SdkActivationConfig, SdkActivationError_, } from "./activation-client.js";
|
|
9
|
+
export { type SdkActivationError, SdkActivationErrorSchema, type SdkActivationLimits, SdkActivationLimitsSchema, type SdkActivationRequest, SdkActivationRequestSchema, type SdkActivationResponse, SdkActivationResponseSchema, type SdkIdentifier, SdkIdentifierSchema, } from "./types.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/_activation/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACN,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,mBAAmB,GACnB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACN,KAAK,kBAAkB,EACvB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,KAAK,oBAAoB,EACzB,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,2BAA2B,EAC3B,KAAK,aAAa,EAClB,mBAAmB,GACnB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inlined copy of @heossi/qnsi-sdk-activation (workspace package, not published).
|
|
3
|
+
* Bundled here so @heossi/qnsi has no external @heossi/qnsi-* dependencies.
|
|
4
|
+
* Keep this folder in sync with packages/sdk-activation/src/ when changes
|
|
5
|
+
* land upstream — both files are minimal (activation-client.ts +
|
|
6
|
+
* types.ts) so a manual diff is tractable.
|
|
7
|
+
*/
|
|
8
|
+
export { activateSdk, clearActivationCache, getActivationLimits, getCachedActivation, SdkActivationError_, } from "./activation-client.js";
|
|
9
|
+
export { SdkActivationErrorSchema, SdkActivationLimitsSchema, SdkActivationRequestSchema, SdkActivationResponseSchema, SdkIdentifierSchema, } from "./types.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/_activation/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACN,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EAEnB,mBAAmB,GACnB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAEN,wBAAwB,EAExB,yBAAyB,EAEzB,0BAA0B,EAE1B,2BAA2B,EAE3B,mBAAmB,GACnB,MAAM,YAAY,CAAC"}
|