Go SDK

Module path: github.com/cuilabs/qnsp-public/sdks/go/qnsp ([source](https://github.com/cuilabs/qnsp-public/tree/main/sdks/go/qnsp), [changelog](https://github.com/cuilabs/qnsp-public/blob/main/sdks/go/qnsp/CHANGELOG.md)).

Go SDK

Module path: github.com/cuilabs/qnsp-public/sdks/go/qnsp (source, changelog).

Installation

go get github.com/cuilabs/qnsp-public/sdks/go/qnsp@latest

The base module pulls in only the standard library. The optional qnsp/crypto subpackage links against liboqs via liboqs-go; if you do not import qnsp/crypto, no native dependency is required.

To use qnsp/crypto you need liboqs and pkg-config available at build time:

Platform Command
macOS brew install liboqs pkg-config
Debian/Ubuntu apt install liboqs-dev pkg-config
From source https://github.com/open-quantum-safe/liboqs

You may also need to set PKG_CONFIG_PATH to include the liboqs-go.pc file shipped inside the module cache ($GOPATH/pkg/mod/github.com/open-quantum-safe/liboqs-go@<version>/.config).

Requires Go 1.22+.

Quick start

package main

import (
	"context"
	"encoding/base64"
	"os"

	"github.com/cuilabs/qnsp-public/sdks/go/qnsp"
	"github.com/cuilabs/qnsp-public/sdks/go/qnsp/audit"
	"github.com/cuilabs/qnsp-public/sdks/go/qnsp/kms"
	"github.com/cuilabs/qnsp-public/sdks/go/qnsp/vault"
)

func main() {
	c, err := qnsp.NewClient(qnsp.ClientOptions{APIKey: os.Getenv("QNSP_API_KEY")})
	if err != nil { panic(err) }
	defer c.Close()
	ctx := context.Background()

	// Vault
	c.Vault().CreateSecret(ctx, vault.CreateSecretRequest{
		Name:       "openai-api-key",
		PayloadB64: base64.StdEncoding.EncodeToString([]byte("sk-...")),
		Algorithm:  "ml-kem-768",
	}, "")

	// KMS
	key, _ := c.KMS().CreateKey(ctx, kms.CreateKeyRequest{Algorithm: "ml-dsa-65", Purpose: "signing"}, "")
	sig, _ := c.KMS().Sign(ctx, key["keyId"].(string), []byte("hello"), "")

	// Audit
	c.Audit().LogEvent(ctx, audit.LogEventRequest{
		EventType: "model.inference",
		Payload:   map[string]any{"modelId": "gpt-4o"},
	}, "")
}

Modules

The SDK ships nine customer-facing modules that mirror the QNSP services callable through the edge gateway today:

Module Source What it wraps
qnsp/vault vault/vault.go apps/vault-service (/vault/v1)
qnsp/kms kms/kms.go apps/kms-service (/kms/v1)
qnsp/audit audit/audit.go apps/audit-service (/audit/v1)
qnsp/tenant tenant/tenant.go apps/tenant-service (/tenant/v1)
qnsp/access access/access.go apps/access-control-service (/access/v1)
qnsp/billing billing/billing.go apps/billing-service (/billing/v1)
qnsp/cryptoinventory cryptoinventory/cryptoinventory.go apps/crypto-inventory-service (/crypto/v1)
qnsp/storage storage/storage.go apps/storage-service (/storage/storage/v1)
qnsp/search search/search.go apps/search-service (/search/v1)
qnsp/crypto crypto/ liboqs-go 0.12.0 (local PQC primitives)

Every subclient also exposes Do(ctx, method, path, body, query, idempotencyKey) so endpoints not yet typed can be called without dropping to raw net/http.

Webhook verification

event, err := qnsp.ParseWebhook(
    body,
    r.Header.Get("X-QNSP-Signature"),
    r.Header.Get("X-QNSP-Timestamp"),
    os.Getenv("QNSP_WEBHOOK_SECRET"),
    qnsp.MaxWebhookSkew,
    time.Time{},
)

qnsp.MaxWebhookSkew defaults to 5 minutes — pass your own time.Duration to tighten it.

Error handling

All errors implement qnsp.Error. Use errors.As to pull out the structured fields:

import "errors"

if _, err := c.Vault().GetSecret(ctx, "missing"); err != nil {
    var apiErr *qnsp.APIError
    if errors.As(err, &apiErr) {
        fmt.Println("HTTP", apiErr.StatusCode, apiErr.Code)
    }
}

Activation + introspection

tenantID, _ := c.TenantID(ctx)
tier, _     := c.Tier(ctx)
limits, _   := c.Limits(ctx)
sseOn, _    := c.HasFeature(ctx, "sseEnabled")

The activation handshake runs lazily on first service call. Call c.EnsureActivated(ctx) to surface API-key errors at startup instead.