Skip to content

Reference source · 0.1.0-dev.11

sdks.md

docs/sdks.md · Download original file

# Backend SDKs and local package verification

OPRP now has locally installable TypeScript, Python and .NET prototype SDKs for version `0.1.0-dev.11`. They implement the same encrypted exchange, Host-issued grants, bounded refresh, scoped clinical operations, synchronization, stable read pages, durable local mirrors and optional callbacks. Clinical policy, patient/representative decisions, network hosting, key custody and at-rest encryption stay outside the client libraries.

The packages are development artifacts, not public registry releases or production-certified software. They have not been published to npm, PyPI or NuGet, and use Apache 2.0 for OPRP original materials, with their bundled notices. No Convey-operated address registry, token service or certificate authority is required.

## Runtime and cryptographic implementations

| SDK | Runtime | Post-quantum provider | Verified scope |
| --- | --- | --- | --- |
| TypeScript `@convey/oprp-sdk` | Node 24 with native ML-KEM/ML-DSA APIs; tested 24.19.0. | Node/OpenSSL 3.5.7. | Fresh local npm installation, declaration typecheck, compiled entry point and the complete reference Host/queue/receiver tests. |
| Python `oprp-sdk` | Python 3.12+; tested 3.12.14. | PQClean through pinned `pqcrypto 0.3.4`; `cryptography 46.0.5` for AES/HKDF. | Installed wheel, independent envelope/discovery/status checks, common clinical/authorization/recovery/receiver/queue scenarios. |
| .NET `Convey.Oprp.Sdk` | .NET 10; tested SDK 10.0.401/runtime 10.0.12. | Explicit local `PythonPqProvider` for ML-KEM/ML-DSA; managed C# envelope/framing/trust/serialization and platform AES/HKDF. | Fresh local NuGet installation, zero-warning build, common clinical/authorization/recovery/receiver/queue scenarios. |

On the development macOS arm64 host, `MLKem.IsSupported` and `MLDsa.IsSupported` both report false. Microsoft exposes the runtime support checks for [ML-KEM](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.mlkem?view=net-10.0) and [ML-DSA](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.mldsa?view=net-10.0); availability must be tested on the target platform.

The .NET prototype therefore explicitly requires a local Python executable with the OPRP wheel installed. Its provider supplies only key generation, signatures and KEM primitives through anonymous subprocess pipes. Private inputs are not command arguments or logs, and the provider makes no network calls. It never substitutes a classical algorithm. This is a functional portability path with process/runtime/key-copy overhead; a reviewed native .NET provider and protected platform key integration remain work before a production SDK claim. Applications can supply a different `IPqProvider` conforming to the same primitives.

## Build the packages

From `protocol/`, install the existing Node dependencies, Python runtime dependencies and pinned build tools. .NET 10 must already be installed.

```sh
npm ci
python3.12 -m venv .venv
.venv/bin/python -m pip install -r python/requirements.txt -r python/build-requirements.txt
npm run package:sdks
npm run sdk:conformance
```

`OPRP_PYTHON` can select an already configured Python executable. `package:sdks` compiles JavaScript/declarations, builds the wheel and NuGet package, then installs all three into fresh local consumers. The NuGet consumer has only a local package source; the npm consumer installs offline with scripts disabled. Python packaging uses installed pinned build tools without resolving runtime dependencies during this local verification. Generated package output is retained in `releases/0.1.0-dev.11/`; test consumers/caches live under ignored `.demo/` directories.

Packages:

- [TypeScript installation archive](../releases/0.1.0-dev.11/convey-oprp-sdk-0.1.0-dev.11.tgz)
- [Python wheel](../releases/0.1.0-dev.11/oprp_sdk-0.1.0.dev11-py3-none-any.whl)
- [.NET NuGet package](../releases/0.1.0-dev.11/Convey.Oprp.Sdk.0.1.0-dev.11.nupkg)
- [Package checksums](../releases/0.1.0-dev.11/checksums.json)

The build command does not publish packages or the documentation website. Package timestamps may vary between builds; the checksum file records the exact current artifacts rather than asserting reproducible binary output.

## Common client contract

All SDKs support request/status/cancellation of authorization, token replacement, planned requester-rotation exchange, current reads, generic clinical create/update/delete/history, scoped snapshot/change polling, export retrieval, subscription registration/status/cancellation, and signed discovery adoption. Python and .NET also verify archive integrity/membership and encrypt/decrypt independent backups. Their archive helpers do not claim the complete Host importer's clinical/history/handoff conformance checks.

| Concern | TypeScript | Python | .NET |
| --- | --- | --- | --- |
| Client | `Client` | `Client` | `Client` |
| Current trust/status | Persistent SQLite `TrustStore` | Persistent SQLite `TrustStore` | `TrustStore` with atomic protected persistence hook/snapshot. |
| Transport | `httpsTransport` | `https_transport` | `HttpsTransport.Send` |
| Approval request | `requestAccess` | `request_access` | `RequestAccess` |
| Generic clinical operations | `createResource`, `readResource`, `updateResource`, `deleteResource`, `resourceHistory` | Corresponding snake_case methods. | Corresponding PascalCase methods. |
| Synchronization | `syncSnapshot`, `changes` | `snapshot`, `changes` | `Snapshot`, `Changes` |
| Durable writes | SQLite `DurableQueue` with typed methods. | SQLite `DurableQueue` accepting stable protected-operation intents. | `DurableQueue` with atomic persistence hook and immutable state proposals. |
| Durable mirrors | SQLite `DurableMirror` | SQLite `DurableMirror` | `DurableMirror` with atomic persistence hook. |
| Callback handling | SQLite `NotificationReceiver` | SQLite `NotificationReceiver` | `NotificationReceiver` with atomic persistence hook. |
| Portable backup | Archive verification/encryption helpers. | `verify_archive`, `encrypt_backup`, `decrypt_backup` | `Portability` integrity/encryption helpers. |

Python refresh calls serialize within one client instance through a lock; TypeScript serializes a refresh promise and .NET uses a semaphore. Each can persist its logical refresh ID before sending. A lost response leaves the same logical ID available after state restoration, within the Host's bounded recovery period. Persistence failure before transmission sends nothing. These are single-instance mechanisms; cross-process token coordination remains unresolved.

Discovery adoption validates the independently chosen address authority, current Host credential, expected patient and monotonic generation. A changed Host/key/patient clears old grant/refresh state. Queue route adoption awaits client persistence before changing the durable route. Fresh destination authorization and snapshot/cursor are required after migration. A resource grant never authorizes another patient or resource type.

## TypeScript use

Install the local tarball into a backend application:

```sh
npm install /absolute/path/to/convey-oprp-sdk-0.1.0-dev.11.tgz
```

```ts
import { Client, TrustStore, httpsTransport, SCOPES } from '@convey/oprp-sdk';
const client = new Client({
  identity, credential, hostCredential, hostId, trust,
  transport: httpsTransport(endpoint),
  persistState: async state => protectedStore.save(state),
});
await client.requestAccess({
  patient, scopes: [SCOPES.conditionRead, SCOPES.conditionCreate],
  requested_duration_seconds: 86400, refresh_requested: true,
});
```

`identity`, current credentials, constrained roots/fresh status and the endpoint are supplied through verified enrollment/discovery. The example assumes access was granted before later clinical operations; pending approval must be checked through the Host's own chosen process. This package targets Node backends, not browser-delivered organization private keys.

## Python use

```sh
python -m pip install /absolute/path/to/oprp_sdk-0.1.0.dev11-py3-none-any.whl
```

```py
from oprp_sdk import Client, TrustStore, https_transport
trust = TrustStore(policies, 'trust.sqlite')
for evidence in fresh_signed_status:
    trust.ingest(evidence, now)
client = Client(identity, credential, host_credential, trust,
                https_transport(endpoint), persist=protected_store.save)
decision = client.request_access(patient, ['patient/Condition.rs'], 86400)
```

Call `trust.close()` separately. Application-owned persistence protects key material and token state. The package also contains the local `.NET` primitive-provider entry point; configuring it never sends keys to a remote service.

## .NET use

Add `releases/0.1.0-dev.11/` as a local NuGet source and reference `Convey.Oprp.Sdk` version `0.1.0-dev.11`. Point the primitive provider to a Python environment with the OPRP wheel and pinned dependencies installed.

```cs
var crypto = new PythonPqProvider(pythonExecutable);
var trust = new TrustStore(policies, crypto, protectedLedger.Save);
var transport = new HttpsTransport(endpoint);
var client = new Client(identity, credential, hostCredential, trust, crypto,
    transport.Send, persist: state => protectedTokenStore.SaveAsync(state));
var decision = await client.RequestAccess(patient,
    ["patient/Condition.rs"], 86400);
```

`AtomicStateFile` is a reference adapter using replacement of a flushed file, with owner-only Unix creation permissions. Its contents remain plaintext; encryption, Windows ACLs, directory custody, backups, durable directory synchronization and multi-process ownership are operator responsibilities. A custom persistence hook must atomically accept the complete proposed state before returning. The queue/receiver publish a state transition only after this callback succeeds. Secure platform key handles and an asynchronous in-process PQ provider remain future improvements.

## Conformance evidence

[sdk-conformance.ts](../scripts/sdk-conformance.ts) imports the fresh TypeScript package and starts installed Python/.NET clients as local subprocess peers. Their encrypted messages reach the reference Host through a stdio test transport; this suite does not by itself exercise Internet networking. The existing HTTPS demos cover the reference network workflow. The Python primitives are independent of Node/OpenSSL; .NET independently implements its message framing, AES/HKDF, trust/client/receiver logic while using the Python PQ primitive provider.

The common Python/.NET scenario verifies conditional permission, duplicate-safe generic create, read/update/conflict/delete/vread/history, scoped changes, refresh persistence failure before transmission, lost-refresh response and state restoration, unchanged approved end, signed archive/independent AES backup including wrong-key rejection, signed callback challenge, receiver restart/lost-ack deduplication, queued lost-write retry, persisted key revocation and current grant revocation. TypeScript's installed entry point and fresh consumer declarations are checked, while its complete behavior is covered by the 104-test reference suite and executable demos.

A shared compact-JSON corpus covers ordinary binary64 thresholds, indexed object keys, Unicode, escapes and field preservation. It is not a complete ECMAScript serialization proof or RFC 8785 conformance suite. Large/exceptional numeric/text inputs, general FHIR profiles and exhaustive malformed-message fuzzing remain release work. Planned rotation and representative proof helpers are present in each SDK; their broader cross-runtime scenarios and negative cases need expansion.

Shared authenticated rejection cases and field/security-label mirror invalidation are documented in [negative conformance](negative-conformance.md) and [visibility](visibility.md).

**Next:** deployable Host operations and secure persistence adapters; broader generated conformance and a reviewed native .NET primitive provider remain required.

See [pagination and mirrors](pagination-mirrors.md) for paged client signatures, staging and change commits, stale-read policy and cache invalidation. Shared package scenarios additionally exercise paged history, mirror restart/deletion, retention-gap rebuilding, outage blocking and revocation.

## External clinical validation update

The [external clinical validation guide](external-clinical-validation.md) supplies six versioned R4 profiles and selected US Core 9.0.0 targets. The [durable validation guide](durable-clinical-validation.md) adds full offline dependency locking, finite local terminology and restartable intake/migration jobs. Setup requires Java and a verified dependency-cache copy. Structural-only mode advertises disabled terminology; local mode rejects unavailable systems and does not include broad licensed clinical vocabularies. Host authorization and conditional patient approval remain separate.