osp-provider-runtime
Thin, boring runtime harness for OSP providers.
This package handles RabbitMQ message plumbing so provider implementations can focus on business logic.
What it does (v0.1)
- Parses a versioned request envelope.
- Builds provider
RequestContext/ProviderRequestand callsexecute(...). - Emits canonical asynchronous task updates and synchronous control-RPC replies.
- Applies explicit ack/requeue/dead-letter decisions.
- Emits structured logs for delivery decisions.
- Supports explicit runtime knobs for prefetch/concurrency/retries/transport timeouts/DLQ.
- Accepts contract_v1 request envelopes.
- Provides
ProviderIdentityso providers derive the same RabbitMQ queue/binding, routing prefix, and signing source fromPROVIDER,PROVIDER_INSTANCE, and optionalPROVIDER_INSTANCE_ID.
Provider identity
Use a provider family for permissions and API requests, then add an instance only when you need a separate runtime lane:
from osp_provider_runtime import ProviderIdentity
identity = ProviderIdentity(
provider="nrec",
instance="pr",
instance_id=37,
)
identity.routing_prefix # "nrec.pr.37"
identity.request_queue # "provider.nrec.pr.37"
identity.request_binding # "nrec.pr.37.#"
identity.signing_provider # "nrec_pr"
The common case stays small: ProviderIdentity("vmware", "dev") gives the
vmware.dev routing prefix and vmware_dev signing source. Signing deliberately
uses only provider + instance, so all nrec.pr.<id> runtimes share the
nrec_pr signing scope without a separate override knob.
Result payload conventions
Provider results should keep ProviderResult.data focused on the resolved
values for the task. The runtime builds the full update payload envelope:
success: provider outcome flag;falsestill represents a completed no-op or degraded outcomeresolved: yourProviderResult.data(after runtime normalization)provenance: optional; extracted fromProviderResult.data["provenance"]dry_run: derived from the request payload
Raise a ProviderError when the task should enter a failed lifecycle state.
ProviderResult(success=False) does not turn a completed outcome into a task
failure.
Special keys in ProviderResult.data:
progress_events(list): lifted into the update payload and removed fromresolvedto avoid duplicate TaskEvent rows.provenance(dict): lifted into the top-levelprovenancefield.
Avoid embedding envelope-shaped keys (requested, resolved,
request_input, request_defaults) inside ProviderResult.data. The runtime
will drop them to keep the stored result compact and predictable.
The orchestrator already owns the original task request. Provider updates do not echo it; HTTP and CLI read models compose request and result when needed.
What it does not do
- No provider framework.
- No plugin system.
- No workflow orchestration.
Install
pip install osp-provider-runtime
Development
env -u VIRTUAL_ENV uv sync --extra dev
hatch shell
hatch run dev:check
hatch run dev:build
hatch run dev:verify
Runtime Knobs
Set these via RuntimeConfig in your provider runtime_app.py:
prefetch_count(default1)concurrency(default1)max_attempts(default5)idempotency_cache_max_entries(default1024)dead_letter_exchange(optional)dead_letter_routing_key(optional)heartbeat_seconds(default60)blocked_connection_timeout_seconds(default30)updates_signing_enabled(defaultFalse)signing_kid(required when signing enabled)signing_secret(UTF-8 shared secret; set this or_b64)signing_secret_b64(base64-encoded shared secret; preferred for random bytes)
Update Emission
Use TaskReporter for provider task lifecycle updates. The runtime keeps
transport details compatible with orchestrator consumers.
Docs:
docs/runtime-contract.mddocs/provider-updates.mddocs/migration-task-reporter.mddocs/runtime-upgrade-checklist.mddocs/release-notes-task-reporter.md
Tag and push:
git tag v0.2.0
git push origin v0.2.0
Release files for osp-provider-runtime 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| osp_provider_runtime-0.3.0.tar.gz | 94.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| osp_provider_runtime-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 136.4 kB
Release files / osp_provider_runtime-0.3.0.tar.gz
| Download URL | osp_provider_runtime-0.3.0.tar.gz |
|---|---|
| Size | 94.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f969eac1f02969227db835ae558a087151985ef9415fa0a25bfcf06662a4f196
|
|
BLAKE2b-256 checksum How to use checksums |
419ab3a8d21935c7658c41664af3b556ebb924ef6713237c28e62790a1a1e9b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / osp_provider_runtime-0.3.0-py3-none-any.whl
| Download URL | osp_provider_runtime-0.3.0-py3-none-any.whl |
|---|---|
| Size | 42.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cd8b05f0508032af05c10121aef8cc7bfab62c0d42d310dea313d46cf84968d0
|
|
BLAKE2b-256 checksum How to use checksums |
dade09b2ba81c71ec0933a8a3c1c40af27ad4c2be6dfc8106a2b1af8bd49fdb2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|