Skip to content
Browse documentation

OPRP 0.1.0-dev.11 · Draft documentation

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 and ML-DSA; 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.

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:

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:

npm install /absolute/path/to/convey-oprp-sdk-0.1.0-dev.11.tgz
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

python -m pip install /absolute/path/to/oprp_sdk-0.1.0.dev11-py3-none-any.whl
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.

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 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 and visibility.

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

See pagination and mirrors 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 supplies six versioned R4 profiles and selected US Core 9.0.0 targets. The durable validation guide 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.

View source

Documentation follows the experimental reference implementation.