API reference¶
Auto-generated from docstrings via mkdocstrings.
Conventions¶
- Only names exported from the top-level
ocx_sdkpackage (and the one public submodule,ocx_sdk.bootstrap) are public. Everything reachable through any other underscored module path is package-private and may change without notice — pre-1.0, breaking changes ship without shims. - Docstrings follow Google style.
Raises:sections list every exception a method may raise from the SDK's own hierarchy; lower-layer exceptions are wrapped and preserved on__cause__.- Every method mirrors one ocx command; see the command ↔ method map for the full correspondence, and environment & exit codes for the wire-level detail behind the typed surface.
ocx_sdk
¶
Python SDK for OCX.
ocx-sdk drives the ocx binary rather than reimplementing it: ocx owns
resolution, verification, and the identifier grammar, and this package gives
you typed, CWD-independent handles over the commands it exposes.
from ocx_sdk import Ocx, bootstrap
ocx = Ocx(exe=bootstrap.ensure())
project = ocx.project("/srv/build")
project.pull()
project.exec(["task", "verify"])
This module is the API. Everything listed in __all__ is the stable
surface; every other module is underscored and package-private, and the one
public submodule is ocx_sdk.bootstrap. Reaching into an underscored path
means the next release may move it without notice — pre-1.0, breaking
changes ship without shims.
Start at Ocx for the runtime API and bootstrap.ensure for provisioning.
UNSET
module-attribute
¶
The default for every per-call retry=/timeout=, meaning "not given".
Public so that a wrapper around this SDK can pass a caller's override
straight through without having to invent its own three-state sentinel:
def deploy(*, retry: MaybeRetry = UNSET): ocx.package.push(..., retry=retry).
MANAGED_CONFIG_DISABLED
module-attribute
¶
Wire sentinel that force-disables the managed config tier for a spawn.
MIN_SUPPORTED
module-attribute
¶
Oldest ocx the SDK accepts; below it the compat gate raises VersionCompatError.
TESTED_OCX_VERSION
module-attribute
¶
The ocx version this SDK's contract tests run against.
ConfigCommands
dataclass
¶
The ocx config command group — the corporate managed-config tier.
setup
¶
setup(*, managed_config: str | None = None, dry_run: bool = False, force: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> ConfigSetupReport
Adopt, or clear, the managed-config tier.
Installs no binary and touches no shell profile — the
automation-shaped counterpart to self setup --managed-config.
| PARAMETER | DESCRIPTION |
|---|---|
managed_config
|
An OCI reference to a managed-config artifact.
TYPE:
|
dry_run
|
Report the intended actions without writing.
TYPE:
|
force
|
Overwrite a managed fence that carries local edits.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ConfigSetupReport
|
The status ocx recorded. |
| RAISES | DESCRIPTION |
|---|---|
DirtyRcBlockError
|
The fence carries local edits and |
Source code in src/ocx_sdk/_client.py
update
¶
update(version: str | None = None, *, check_only: bool = False, pause: str | None = None, resume: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> ConfigUpdateReport
Refresh the managed-config snapshot from the registry.
Unlike the project-tier lock --check, this command answers --check
with a full payload — status reads checked or check_unavailable.
| PARAMETER | DESCRIPTION |
|---|---|
version
|
A tag,
TYPE:
|
check_only
|
Report status — drift, pause, pin — without fetching
or swapping. ocx's
TYPE:
|
pause
|
Hold the background refresh for a duration such as
TYPE:
|
resume
|
Clear an active pause and refresh immediately.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ConfigUpdateReport
|
The tier's status, source, digest, and policy. |
Source code in src/ocx_sdk/_client.py
Ocx
¶
Ocx(exe: str | Path | None = None, *, config: OcxConfig | None = None, host_env: HostEnv | None = None, on_log: Callable[[str], None] | None = None)
A handle on one ocx binary.
Construction resolves the binary once — the explicit exe, then
OCX_SDK_EXE, then PATH, then ocx's own install symlink — and pins the
result for the handle's lifetime. Every call composes its own argv and
child environment, and the handle exposes no mutators, so it is safe to
share across threads, tasks, and event loops.
The first typed call probes ocx version and refuses a binary older than
MIN_SUPPORTED; newer than TESTED_OCX_VERSION is expected and only
noted at DEBUG.
A long-lived handle keeps running the binary it resolved, so a consumer
shaped like a daemon should reconstruct Ocx() periodically to pick up
what an ocx self update replaced underneath it.
Example
| ATTRIBUTE | DESCRIPTION |
|---|---|
exe |
The resolved binary this handle runs.
TYPE:
|
session_config |
The
TYPE:
|
| PARAMETER | DESCRIPTION |
|---|---|
exe
|
An explicit binary path.
TYPE:
|
config
|
Session configuration.
TYPE:
|
host_env
|
The environment children inherit from.
TYPE:
|
on_log
|
Called with each redacted stderr line from the pump thread, so it must be thread-safe. Rejected on async paths.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
OcxNotFoundError
|
No binary was found; the message names
|
Source code in src/ocx_sdk/_client.py
session_config
property
¶
session_config: OcxConfig
The OcxConfig this handle spawns under.
Read-only, and the config itself is frozen: derive a variant with
with_config(...) rather than trying to write through this. Not
spelled config because ocx.config is the ocx config command
group, and command alignment wins over the shorter name.
package
property
¶
package: PackageCommands
The ocx package command group — machine tier, no project path.
with_config
¶
with_config(**overrides: Unpack[ConfigOverrides]) -> Ocx
Derive a handle with some configuration fields replaced.
The derived handle shares this one's binary, host environment,
on_log, and compatibility memo — only the configuration differs.
Changing any of the others means constructing a fresh Ocx.
| PARAMETER | DESCRIPTION |
|---|---|
**overrides
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Ocx
|
The derived handle. |
| RAISES | DESCRIPTION |
|---|---|
TypeError
|
An override names no |
Source code in src/ocx_sdk/_client.py
project
¶
project(path: str | Path) -> Project
Return a project-tier handle rooted at path.
The path is made absolute immediately, so the handle keeps targeting the same project no matter what the working directory does later.
ocx's --project names the project file, the way Cargo's
--manifest-path does, and accepts any filename. A directory is the
obvious thing to pass and the common case, so it is resolved to the
ocx.toml inside it.
A path that does not exist yet — which is every path init() is
called on — is read by its name: a .toml suffix means the file,
anything else means the directory. Guessing "file" there would make
project('/srv/build').init() write /srv/ocx.toml, one level above
where the caller pointed.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
The project directory, or the project file directly.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Project
|
A handle whose every call carries |
Source code in src/ocx_sdk/_client.py
version
¶
Return the binary's version, as ocx version prints it.
Reads the plain output — a bare semver line — which is ocx's
documented stable script contract and the recorded exception to the
--format json pinning rule. This call is the compatibility probe
itself, so it never triggers the gate and never raises
VersionCompatError: asking an unsupported binary what it is has to
work. The richer JSON envelope is available through
VersionInfo.from_json(ocx.invoke(["--format", "json",
"version"]).stdout).
| PARAMETER | DESCRIPTION |
|---|---|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
The version string, whitespace stripped. |
Source code in src/ocx_sdk/_client.py
about
¶
Report what this ocx build is and where it keeps its state.
| PARAMETER | DESCRIPTION |
|---|---|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
AboutInfo
|
The parsed |
Source code in src/ocx_sdk/_client.py
login
¶
login(registry: str | None = None, *, username: str, token: str, allow_insecure_store: bool = False, verify: bool = True, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> LoginResult
Authenticate to a registry and let ocx persist the credentials.
The token travels on stdin through --password-stdin, never in argv,
and is redacted from logs and errors for the duration of the call.
Retries are off by default: a timed-out login exits 75, and
re-sending credentials on a timeout is the auth-retry mistake the
policy exists to prevent. Pass retry= explicitly to override.
| PARAMETER | DESCRIPTION |
|---|---|
registry
|
The registry hostname.
TYPE:
|
username
|
The account name. Required — the SDK never prompts.
TYPE:
|
token
|
The password or token, written to ocx's stdin.
TYPE:
|
allow_insecure_store
|
Permit the plaintext
TYPE:
|
verify
|
Check the credentials against the registry before storing them.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy. Defaults to no retries.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
LoginResult
|
The registry and username ocx recorded. |
Source code in src/ocx_sdk/_client.py
logout
¶
logout(registry: str | None = None, *, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> LogoutResult
Drop the stored credentials for a registry.
| PARAMETER | DESCRIPTION |
|---|---|
registry
|
The registry hostname.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
LogoutResult
|
The registry ocx cleared. Clearing an absent entry is not an |
LogoutResult
|
error. |
Source code in src/ocx_sdk/_client.py
clean
¶
clean(*, dry_run: bool = False, force: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> tuple[CleanEntry, ...]
Remove unreferenced objects from the local object store.
mutating=not dry_run (D5), as copy: the preview writes nothing.
The rows are the read-only view of what the store holds loose — the
kind: "consent" entries among them are the stamps OcxConfig.consent
governs, so a preview says which projects a real run would deactivate.
| PARAMETER | DESCRIPTION |
|---|---|
dry_run
|
Report what would be removed and remove nothing.
TYPE:
|
force
|
Ignore the per-user project registry and collect every
unreferenced package, including ones a registered
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[CleanEntry, ...]
|
One row per removal, or intended removal. |
Source code in src/ocx_sdk/_client.py
invoke
¶
invoke(argv: Sequence[str], *, check: bool = True, capture: bool = True, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> CommandResult
Run an arbitrary ocx command line — the raw escape hatch.
The configured globals and the composed child environment still
apply; presentation does not, so ask for --format json yourself if
you intend to parse the output. Commands reached this way are
possible but unsupported: nothing pins their shape, and the
compatibility gate does not run.
| PARAMETER | DESCRIPTION |
|---|---|
argv
|
The command and its arguments, without the binary.
TYPE:
|
check
|
Raise on a non-zero exit instead of returning it.
TYPE:
|
capture
|
Pipe and capture both streams.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CommandResult
|
The exit code and captured output. |
| RAISES | DESCRIPTION |
|---|---|
OcxProcessError
|
A non-zero exit under |
OcxTimeoutError
|
The timeout expired. |
Source code in src/ocx_sdk/_client.py
invoke_async
async
¶
invoke_async(argv: Sequence[str], *, check: bool = True, capture: bool = True, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> CommandResult
Run an arbitrary ocx command line on the event loop.
The async twin of invoke. Cancelling the awaiting task terminates
the child before the CancelledError propagates.
| PARAMETER | DESCRIPTION |
|---|---|
argv
|
The command and its arguments, without the binary.
TYPE:
|
check
|
Raise on a non-zero exit instead of returning it.
TYPE:
|
capture
|
Pipe and capture both streams.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CommandResult
|
The exit code and captured output. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
The handle carries an |
OcxProcessError
|
A non-zero exit under |
OcxTimeoutError
|
The timeout expired. |
Source code in src/ocx_sdk/_client.py
spawn
¶
Start an arbitrary ocx command line and return the live Popen.
No timeout and no pumps: waiting, draining pipes, and killing belong
to the caller, exactly as with a bare Popen.
| PARAMETER | DESCRIPTION |
|---|---|
argv
|
The command and its arguments, without the binary.
TYPE:
|
**popen_kw
|
Forwarded to
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Popen[Any]
|
The running child. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
TypeError
|
|
Source code in src/ocx_sdk/_client.py
spawn_async
async
¶
Start an arbitrary ocx command line on the event loop.
| PARAMETER | DESCRIPTION |
|---|---|
argv
|
The command and its arguments, without the binary.
TYPE:
|
**popen_kw
|
Forwarded to the subprocess factory.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Process
|
The running child. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
TypeError
|
|
Source code in src/ocx_sdk/_client.py
PackageCommands
dataclass
¶
The ocx package command group — machine tier.
Package operations act on the $OCX_HOME store and its candidate and
current symlinks. They take no project path and are CWD-independent by
construction; a path appears only where the CLI itself takes one.
Every method is multi-identifier native, mirroring the CLI's PKG...
with one shared resolution.
install
¶
install(*refs: PackageLike, platform: str | None = None, select: bool = False, verify: bool | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> InstallReport
Install packages into the store.
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Package identifiers.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
select
|
Also make each installed version current.
TYPE:
|
verify
|
Verify each package's Sigstore signature before
installing.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
InstallReport
|
The installed packages, keyed by the identifier as given. |
| RAISES | DESCRIPTION |
|---|---|
OcxProcessError
|
ocx 0.6 verifies a covered package's signature before installing, so this call can fail where the identical call against a 0.5.x binary succeeded — no code change on the caller's side, only a newer binary. The exit codes, and why none of them retry, are in the guide's "Errors & credentials" section on verification. |
Source code in src/ocx_sdk/_client.py
select
¶
select(*refs: PackageLike, platform: str | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> InstallReport
Make an installed version the current one.
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Package identifiers.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
InstallReport
|
The selected packages, whose |
Source code in src/ocx_sdk/_client.py
uninstall
¶
uninstall(*refs: PackageLike, deselect: bool = False, purge: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> tuple[RemovalResult, ...]
Remove installed candidates.
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Package identifiers.
TYPE:
|
deselect
|
Also drop the
TYPE:
|
purge
|
Delete the object from the store once nothing references it.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[RemovalResult, ...]
|
One row per removal. |
Source code in src/ocx_sdk/_client.py
deselect
¶
deselect(*refs: PackageLike, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> tuple[RemovalResult, ...]
Drop the current symlink, leaving the candidates installed.
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Package identifiers.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[RemovalResult, ...]
|
One row per removal. |
Source code in src/ocx_sdk/_client.py
env
¶
env(*refs: PackageLike, platform: str | None = None, env: Mapping[str, EnvValue] | None = None, resolve: Resolve | None = None, private: bool = False, lazy_mode: LazyMode | None = None, show_patches: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> EnvReport
Report the environment a set of packages composes.
Returns the same envelope as the project-tier env, and carries the
same host snapshot for a hermetic compose().
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Package identifiers.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
env
|
Extra
TYPE:
|
resolve
|
Which store symlink to resolve through —
TYPE:
|
private
|
Compose the private surface instead of the interface
one — ocx's
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
show_patches
|
Include patch-contributed entries.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
EnvReport
|
The typed entries plus the full envelope. |
Source code in src/ocx_sdk/_client.py
exec
¶
exec(refs: Sequence[PackageLike], argv: Sequence[str], *, platform: str | None = None, clean: bool = False, private: bool = False, env: Mapping[str, EnvValue] | None = None, lazy_mode: LazyMode | None = None, records_dir: str | Path | None = None, records_name: str | None = None, capture: bool = True, check: bool = True, timeout: MaybeTimeout = UNSET) -> CommandResult
Run a command in a set of packages' composed environment.
Two positional groups, mirroring the CLI's PKG... -- CMD.... The
child's exit code comes back byte for byte; child processes are
never retried.
| PARAMETER | DESCRIPTION |
|---|---|
refs
|
Package identifiers to compose.
TYPE:
|
argv
|
The command and its arguments. Must not be empty.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
clean
|
Strip the ambient parent environment before composing.
TYPE:
|
private
|
Compose the private surface — ocx's
TYPE:
|
env
|
Extra
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
records_dir
|
Write an execution record — the resolved closure
and executable — under this directory.
TYPE:
|
records_name
|
The record's filename template, over
TYPE:
|
capture
|
Pipe and capture both streams.
TYPE:
|
check
|
Raise on a non-zero child exit instead of returning it.
TYPE:
|
timeout
|
Seconds for the whole run. Omitted takes the config's.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CommandResult
|
The child's exit code and, under |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
OcxProcessError
|
The child exited non-zero under |
OcxTimeoutError
|
The timeout expired. |
Source code in src/ocx_sdk/_client.py
exec_async
async
¶
exec_async(refs: Sequence[PackageLike], argv: Sequence[str], *, platform: str | None = None, clean: bool = False, private: bool = False, env: Mapping[str, EnvValue] | None = None, lazy_mode: LazyMode | None = None, records_dir: str | Path | None = None, records_name: str | None = None, capture: bool = True, check: bool = True, timeout: MaybeTimeout = UNSET) -> CommandResult
Run a command in a packages' environment, on the event loop.
| PARAMETER | DESCRIPTION |
|---|---|
refs
|
Package identifiers to compose.
TYPE:
|
argv
|
The command and its arguments. Must not be empty.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
clean
|
Strip the ambient parent environment before composing.
TYPE:
|
private
|
Compose the private surface — ocx's
TYPE:
|
env
|
Extra
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
records_dir
|
Write an execution record — the resolved closure
and executable — under this directory.
TYPE:
|
records_name
|
The record's filename template, over
TYPE:
|
capture
|
Pipe and capture both streams.
TYPE:
|
check
|
Raise on a non-zero child exit instead of returning it.
TYPE:
|
timeout
|
Seconds for the whole run. Omitted takes the config's.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CommandResult
|
The child's exit code and, under |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
OcxProcessError
|
The child exited non-zero under |
OcxTimeoutError
|
The timeout expired. |
Source code in src/ocx_sdk/_client.py
spawn
¶
spawn(refs: Sequence[PackageLike], argv: Sequence[str], *, platform: str | None = None, clean: bool = False, private: bool = False, env: Mapping[str, EnvValue] | None = None, lazy_mode: LazyMode | None = None, records_dir: str | Path | None = None, records_name: str | None = None, **popen_kw: Any) -> Popen[Any]
Start a command in a packages' environment and return Popen.
| PARAMETER | DESCRIPTION |
|---|---|
refs
|
Package identifiers to compose.
TYPE:
|
argv
|
The command and its arguments. Must not be empty.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
clean
|
Strip the ambient parent environment before composing.
TYPE:
|
private
|
Compose the private surface — ocx's
TYPE:
|
env
|
Extra
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
records_dir
|
Write an execution record — the resolved closure
and executable — under this directory.
TYPE:
|
records_name
|
The record's filename template, over
TYPE:
|
**popen_kw
|
Forwarded to
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Popen[Any]
|
The running child. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
Source code in src/ocx_sdk/_client.py
spawn_async
async
¶
spawn_async(refs: Sequence[PackageLike], argv: Sequence[str], *, platform: str | None = None, clean: bool = False, private: bool = False, env: Mapping[str, EnvValue] | None = None, lazy_mode: LazyMode | None = None, records_dir: str | Path | None = None, records_name: str | None = None, **popen_kw: Any) -> Process
Start a command in a packages' environment, on the event loop.
| PARAMETER | DESCRIPTION |
|---|---|
refs
|
Package identifiers to compose.
TYPE:
|
argv
|
The command and its arguments. Must not be empty.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
clean
|
Strip the ambient parent environment before composing.
TYPE:
|
private
|
Compose the private surface — ocx's
TYPE:
|
env
|
Extra
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
records_dir
|
Write an execution record — the resolved closure
and executable — under this directory.
TYPE:
|
records_name
|
The record's filename template, over
TYPE:
|
**popen_kw
|
Forwarded to the subprocess factory.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Process
|
The running child. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
Source code in src/ocx_sdk/_client.py
which
¶
which(*refs: PackageLike, platform: str | None = None, resolve: Resolve | None = None, lazy_mode: LazyMode | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> Mapping[str, WhichResult]
Resolve installed packages to their paths, downloading nothing.
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Package identifiers.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
resolve
|
Which store symlink to resolve through —
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Mapping[str, WhichResult]
|
A path and kind per identifier. This payload is doc-flagged |
Mapping[str, WhichResult]
|
pre-1.0 upstream and may change shape. |
Source code in src/ocx_sdk/_client.py
inspect
¶
inspect(*refs: PackageLike, platform: str | None = None, env: Mapping[str, EnvValue] | None = None, resolve: bool = False, closure: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> InspectReport
Inspect packages straight from the registry or the store.
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Package identifiers.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
env
|
Extra
TYPE:
|
resolve
|
Add the pinned identifier, digest, layers, and the resolution chain, which at this tier starts with an index hop the project tier skips.
TYPE:
|
closure
|
Add the dependency closure, its surface, and any conflicts.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
InspectReport
|
The inspected packages, whose |
InspectReport
|
identifier at this tier. |
Source code in src/ocx_sdk/_client.py
description_pull
¶
description_pull(*refs: PackageLike, save_readme: str | Path | None = None, save_logo: str | Path | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> InfoResult
Show the description metadata a registry holds for packages.
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Package repositories to query.
TYPE:
|
save_readme
|
Write the README to this file or directory. ocx accepts it for a single package only.
TYPE:
|
save_logo
|
Write the logo to this file or directory. Single package only, as above.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
InfoResult
|
One entry per identifier as given, |
InfoResult
|
holds no description metadata. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
A save target was given for anything other than exactly one package — ocx would refuse it, and refusing here names which argument to drop. |
Source code in src/ocx_sdk/_client.py
deps
¶
deps(*refs: PackageLike, platform: str | None = None, private: bool = False, why: PackageLike | None = None, depth: int | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> DepsReport
Show the dependency tree of installed packages.
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Package identifiers.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
private
|
Include the private, self-only edges — ocx's
TYPE:
|
why
|
Explain why this dependency is pulled in. Matched by registry and repository; the tag is ignored.
TYPE:
|
depth
|
Limit the tree depth.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DepsReport
|
One root per requested package. |
Source code in src/ocx_sdk/_client.py
pull
¶
pull(*refs: PackageLike, platform: str | None = None, verify: bool | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> Mapping[str, str]
Download packages into the store without creating symlinks.
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Package identifiers.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
verify
|
Verify each package's Sigstore signature before storing
it.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Mapping[str, str]
|
A store path per identifier — a bare string here, unlike the |
Mapping[str, str]
|
project tier's |
| RAISES | DESCRIPTION |
|---|---|
OcxProcessError
|
ocx 0.6 verifies a covered package's signature before storing it, so this call can fail where the identical call against a 0.5.x binary succeeded — no code change on the caller's side, only a newer binary. The exit codes, and why none of them retry, are in the guide's "Errors & credentials" section on verification. |
Source code in src/ocx_sdk/_client.py
create
¶
create(path: str | Path, *, identifier: str | None = None, platform: str | None = None, output: str | Path | None = None, metadata: str | Path | None = None, force: bool = False, compression_level: Literal['fast', 'best', 'default'] | None = None, threads: int | None = None, bin_scan: bool | None = None, libc_lint: bool = True, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> None
Bundle a local directory into a package archive.
Writes the bundle, a compiled metadata sidecar when metadata is
given, and a build receipt that push and test read back. There is
nothing to return: ocx prints no payload for this command.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
The package directory to bundle.
TYPE:
|
identifier
|
The identifier the bundle will be published under.
Recorded in the receipt, where
TYPE:
|
platform
|
The platform the content runs on. Required whenever
TYPE:
|
output
|
The output file or directory.
TYPE:
|
metadata
|
A
TYPE:
|
force
|
Overwrite an existing output file.
TYPE:
|
compression_level
|
How hard to compress the bundle.
TYPE:
|
threads
|
Compression threads.
TYPE:
|
bin_scan
|
Scan the content tree for the executables the package
puts on
TYPE:
|
libc_lint
|
Check the packaged binaries against the platform's
declared
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
Source code in src/ocx_sdk/_client.py
2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 | |
test
¶
test(identifier: str, *, script: str | Path, layers: Iterable[str | Path] = (), platform: str | None = None, metadata: str | Path | None = None, output: str | Path | None = None, keep: bool = False, clean: bool = False, private: bool = False, env: Mapping[str, EnvValue] | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> TestResult
Materialize a package locally and run a Starlark test script.
Only the --script form is typed. ocx's trailing -- CMD form
prints the child's stdout verbatim even under --format json, so it
produces nothing parseable — reach for invoke if you need it.
| PARAMETER | DESCRIPTION |
|---|---|
identifier
|
The identifier to materialize under. Tag form only.
TYPE:
|
script
|
Path to the Starlark test script, or
TYPE:
|
layers
|
Layer archives or digest references, base first.
TYPE:
|
platform
|
The platform to resolve against. Omitted reads the build receipt beside the bundle.
TYPE:
|
metadata
|
The compiled metadata sidecar. Required when no file layers are given.
TYPE:
|
output
|
Where to materialize the package.
TYPE:
|
keep
|
Preserve the temporary build directory.
TYPE:
|
clean
|
Strip the ambient parent environment before composing.
TYPE:
|
private
|
Compose the private surface — ocx's
TYPE:
|
env
|
Extra
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
TestResult
|
The outcome: |
TestResult
|
stable machine-readable reason. A failing script is a RESULT |
TestResult
|
(exit 1 still carries the envelope), not an exception — only |
TestResult
|
resolution or usage failures raise. |
Source code in src/ocx_sdk/_client.py
2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 | |
push
¶
push(*layers: str | Path, identifier: str | None = None, platform: str | None = None, metadata: str | Path | None = None, cascade: bool = False, keep_tag: bool | None = None, build_timestamp: Literal['datetime', 'date', 'none'] | None = None, annotations: Mapping[str, str] | None = None, tags_file: str | Path | None = None, sign: bool = False, key: str | None = None, signature_format: SignatureFormat | None = None, rekor_upload: bool | None = None, sbom: str | Path | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> PushResult
Publish a package's layers and metadata to a registry.
Retries are off by default: a push is a registry write, and
re-sending one on a timeout can publish twice. Pass retry=
explicitly when the target is known to be idempotent-safe.
A push that lands and then fails to sign or attest is not rolled
back — a pushed manifest is immutable and OCI offers no un-push —
and the signing failure decides the exit code, so the call raises.
The report survives that: push writes its payload bare at the JSON
root (D11), so catch OcxProcessError, recover the document with
partial_report(err), and parse it with PushResult.from_json. The
package is published, and signatures names which platform failed.
| PARAMETER | DESCRIPTION |
|---|---|
*layers
|
Layer archives or
TYPE:
|
identifier
|
The identifier to publish under. Omitted reads the build receipt beside the bundle.
TYPE:
|
platform
|
The platform the manifest is scoped to. Omitted reads the receipt.
TYPE:
|
metadata
|
The compiled metadata sidecar. Required when no file layers are given.
TYPE:
|
cascade
|
Also advance the rolling tags above this version.
TYPE:
|
keep_tag
|
Write the
TYPE:
|
build_timestamp
|
Append a UTC build-metadata segment to the
published tag, for rolling continuous-deploy versions. The
version core in
TYPE:
|
annotations
|
OCI annotations for the published index.
TYPE:
|
tags_file
|
Append the pushed tag and any cascade tags to this
file, where
TYPE:
|
sign
|
Sign each platform manifest this push writes, inline.
Required — along with
TYPE:
|
key
|
A key reference for the inline signing —
TYPE:
|
signature_format
|
Which signature format(s) the inline signing produces.
TYPE:
|
rekor_upload
|
Upload the inline signature to the transparency
log.
TYPE:
|
sbom
|
After the push, attest this CycloneDX SBOM against the
pushed manifest — sugar for
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy. Defaults to no retries.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
PushResult
|
The published identifier, digest, and tags. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
A signing modifier ( |
OcxProcessError
|
A non-zero exit. When the push itself landed and the signing or the SBOM attestation is what failed, see the partial-failure note above for how to recover the report. |
Source code in src/ocx_sdk/_client.py
2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 | |
description_push
¶
description_push(identifier: PackageLike, *, from_: PackageLike | None = None, readme: str | Path | None = None, logo: str | Path | None = None, title: str | None = None, description: str | None = None, keywords: str | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> CommandResult
Publish description metadata for a package repository (C-003).
ocx prints no JSON payload for this command (D9) — it logs and exits, so there is nothing typed to return.
| PARAMETER | DESCRIPTION |
|---|---|
identifier
|
The package repository to describe.
TYPE:
|
from_
|
Another package to copy the description from, instead of
the field arguments below — ocx's
TYPE:
|
readme
|
The README file to publish.
TYPE:
|
logo
|
The logo file to publish.
TYPE:
|
title
|
The display title to publish.
TYPE:
|
description
|
The prose description to publish.
TYPE:
|
keywords
|
A single delimited keywords string, not a list — ocx's own field is a bare string (C-021).
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy. Defaults to no retries — this is a registry write (D5).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CommandResult
|
The exit code and whatever ocx printed. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
Neither |
NotFoundError
|
|
Source code in src/ocx_sdk/_client.py
2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 | |
sign
¶
sign(ref: PackageLike, *, tags: Iterable[str], tags_file: str | Path | None = None, platform: str | None = None, signature_format: SignatureFormat | None = None, key: str | None = None, rekor_upload: bool | None = None, fulcio_url: str | None = None, rekor_url: str | None = None, identity_token_file: str | Path | None = None, identity_token_stdin: bool = False, no_tty: bool = False, no_cache: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> SweepReport
sign(ref: PackageLike, *, tags: Iterable[str] | None = None, tags_file: str | Path, platform: str | None = None, signature_format: SignatureFormat | None = None, key: str | None = None, rekor_upload: bool | None = None, fulcio_url: str | None = None, rekor_url: str | None = None, identity_token_file: str | Path | None = None, identity_token_stdin: bool = False, no_tty: bool = False, no_cache: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> SweepReport
sign(ref: PackageLike, *, tags: None = None, tags_file: None = None, platform: str | None = None, signature_format: SignatureFormat | None = None, key: str | None = None, rekor_upload: bool | None = None, fulcio_url: str | None = None, rekor_url: str | None = None, identity_token_file: str | Path | None = None, identity_token_stdin: bool = False, no_tty: bool = False, no_cache: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> SignatureReport
sign(ref: PackageLike, *, tags: Iterable[str] | None = None, tags_file: str | Path | None = None, platform: str | None = None, signature_format: SignatureFormat | None = None, key: str | None = None, rekor_upload: bool | None = None, fulcio_url: str | None = None, rekor_url: str | None = None, identity_token_file: str | Path | None = None, identity_token_stdin: bool = False, no_tty: bool = False, no_cache: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> SignatureReport | SweepReport
Sign a package reference with cosign/Sigstore (C-011).
Three call shapes, one method (D2): tags or tags_file sweeps
every matching tag and returns a SweepReport; neither signs ref
alone and returns a SignatureReport.
mutating=True (D5) — retries are off by default; auto-retrying a
Rekor-unavailable failure would amplify the public instance's rate
limiting (D6).
A --signature-format both run where one leg lands and one fails
exits non-zero carrying a full report: catch OcxProcessError,
recover it with partial_report(err), and parse with
SignatureReport.from_json (D10) — SignatureLegReport.error names
which leg died.
key and keyless signing are mutually exclusive with each other's
machinery, not just in spirit. Four flags refuse key outright —
fulcio_url, identity_token_file, identity_token_stdin, and
no_tty. Separately, rekor_upload=False (--no-rekor-upload)
requires key — the opposite direction: it is meaningless for
keyless signing, which cannot skip Rekor. And independently of
key entirely, identity_token_file and identity_token_stdin
conflict with each other — two ways to supply one token.
| PARAMETER | DESCRIPTION |
|---|---|
ref
|
The package reference to sign.
TYPE:
|
tags
|
Sweep these tags instead of signing
TYPE:
|
tags_file
|
Sweep the tags listed in this file. Mutually
exclusive with
TYPE:
|
platform
|
Sign one platform's manifest. Refused alongside
TYPE:
|
signature_format
|
Which signature format(s) to produce.
TYPE:
|
key
|
A key reference —
TYPE:
|
rekor_upload
|
Upload the signature to the transparency log.
TYPE:
|
fulcio_url
|
A non-default Fulcio instance. Conflicts with
TYPE:
|
rekor_url
|
A non-default Rekor instance.
TYPE:
|
identity_token_file
|
Read the OIDC identity token from this
file, for keyless signing without an interactive browser
flow. Conflicts with
TYPE:
|
identity_token_stdin
|
Read the OIDC identity token from stdin.
Conflicts with
TYPE:
|
no_tty
|
Suppress the interactive TTY prompt. Conflicts with
TYPE:
|
no_cache
|
Skip ocx's signing cache.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy. Defaults to no retries.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
SignatureReport | SweepReport
|
A |
SignatureReport | SweepReport
|
when |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
OcxProcessError
|
A non-zero exit — see the partial-failure note above for how to recover a report from one. |
Source code in src/ocx_sdk/_client.py
2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 | |
attest
¶
attest(ref: PackageLike, *, predicate: str | Path, predicate_type: str, tags: Iterable[str], tags_file: str | Path | None = None, platform: str | None = None, signature_format: SignatureFormat | None = None, key: str | None = None, rekor_upload: bool | None = None, fulcio_url: str | None = None, rekor_url: str | None = None, identity_token_file: str | Path | None = None, identity_token_stdin: bool = False, no_tty: bool = False, no_cache: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> SweepReport
attest(ref: PackageLike, *, predicate: str | Path, predicate_type: str, tags: Iterable[str] | None = None, tags_file: str | Path, platform: str | None = None, signature_format: SignatureFormat | None = None, key: str | None = None, rekor_upload: bool | None = None, fulcio_url: str | None = None, rekor_url: str | None = None, identity_token_file: str | Path | None = None, identity_token_stdin: bool = False, no_tty: bool = False, no_cache: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> SweepReport
attest(ref: PackageLike, *, predicate: str | Path, predicate_type: str, tags: None = None, tags_file: None = None, platform: str | None = None, signature_format: SignatureFormat | None = None, key: str | None = None, rekor_upload: bool | None = None, fulcio_url: str | None = None, rekor_url: str | None = None, identity_token_file: str | Path | None = None, identity_token_stdin: bool = False, no_tty: bool = False, no_cache: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> AttestationReport
attest(ref: PackageLike, *, predicate: str | Path, predicate_type: str, tags: Iterable[str] | None = None, tags_file: str | Path | None = None, platform: str | None = None, signature_format: SignatureFormat | None = None, key: str | None = None, rekor_upload: bool | None = None, fulcio_url: str | None = None, rekor_url: str | None = None, identity_token_file: str | Path | None = None, identity_token_stdin: bool = False, no_tty: bool = False, no_cache: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> AttestationReport | SweepReport
Attach an in-toto attestation to a package reference (C-013).
Same three call shapes as sign (D2): tags/tags_file sweeps and
returns a SweepReport; neither attests ref alone and returns an
AttestationReport. mutating=True (D5), retries off by default
(D6).
Carries the identical --key conflict set sign has — this is
enumerated per command rather than delegated to a shared note,
because it is attest's own guard, declared independently in
package_attest.rs alongside package_sign.rs's: four flags
refuse key outright (fulcio_url, identity_token_file,
identity_token_stdin, no_tty); rekor_upload=False
(--no-rekor-upload) requires key, the opposite direction; and
independently of key, identity_token_file conflicts with
identity_token_stdin.
| PARAMETER | DESCRIPTION |
|---|---|
ref
|
The package reference to attest.
TYPE:
|
predicate
|
The predicate document to attest.
TYPE:
|
predicate_type
|
The predicate type URI or its short alias —
ocx's
TYPE:
|
tags
|
Sweep these tags instead of attesting
TYPE:
|
tags_file
|
Sweep the tags listed in this file. Unions with
TYPE:
|
platform
|
Attest one platform's manifest. Refused alongside
TYPE:
|
signature_format
|
Which signature format(s) to produce.
TYPE:
|
key
|
A key reference.
TYPE:
|
rekor_upload
|
Upload to the transparency log.
TYPE:
|
fulcio_url
|
A non-default Fulcio instance. Conflicts with
TYPE:
|
rekor_url
|
A non-default Rekor instance.
TYPE:
|
identity_token_file
|
Read the OIDC identity token from this
file. Conflicts with
TYPE:
|
identity_token_stdin
|
Read the OIDC identity token from stdin.
Conflicts with
TYPE:
|
no_tty
|
Suppress the interactive TTY prompt. Conflicts with
TYPE:
|
no_cache
|
Skip ocx's signing cache.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy. Defaults to no retries.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
AttestationReport | SweepReport
|
An |
AttestationReport | SweepReport
|
|
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
OcxProcessError
|
A non-zero exit. Recover a partial report with
|
Source code in src/ocx_sdk/_client.py
2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 | |
verify
¶
verify(ref: PackageLike, *, platform: str | None = None, certificate_identity: str | None = None, certificate_oidc_issuer: str | None = None, key: str | None = None, signature_format: SignatureFormat | None = None, rekor_url: str | None = None, attestation: bool = False, predicate_type: str | None = None, allow_unlogged_signature: bool = False, no_cache: bool = False, sigstore_trusted_root: str | Path | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> VerificationReport
Verify a package reference's signature or attestation (C-012).
A read — not mutating, and keeps the normal retry default (D5).
Keyless verification needs the identity pair: cosign 2.0 made
--certificate-identity and --certificate-oidc-issuer
hard-required together, because without both a signature from
any Fulcio-certified identity passes (D3). Neither is usable
alongside key.
| PARAMETER | DESCRIPTION |
|---|---|
ref
|
The package reference to verify.
TYPE:
|
platform
|
Verify one platform's manifest.
TYPE:
|
certificate_identity
|
The pinned keyless identity. Required
together with
TYPE:
|
certificate_oidc_issuer
|
The pinned keyless OIDC issuer.
Required together with
TYPE:
|
key
|
A key reference, for key-based verification.
TYPE:
|
signature_format
|
Restrict to one signature format.
TYPE:
|
rekor_url
|
A non-default Rekor instance.
TYPE:
|
attestation
|
Verify an attestation instead of a signature.
TYPE:
|
predicate_type
|
Restrict attestation verification to this
predicate type. Requires
TYPE:
|
allow_unlogged_signature
|
Accept a signature with no transparency log entry.
TYPE:
|
no_cache
|
Skip ocx's verification cache.
TYPE:
|
sigstore_trusted_root
|
A non-default Sigstore trusted root bundle.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
VerificationReport
|
The verified subject, identity, and matching signatures. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
Only one of |
OcxProcessError
|
The signature did not verify — this command's
main outcome, not an edge case. |
Source code in src/ocx_sdk/_client.py
2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 | |
sbom
¶
sbom(ref: PackageLike, *, platform: str | None = None, summary: bool = False, predicate_type: str | None = None, certificate_identity: str | None = None, certificate_oidc_issuer: str | None = None, key: str | None = None, signature_format: SignatureFormat | None = None, sigstore_trusted_root: str | Path | None = None, rekor_url: str | None = None, no_cache: bool = False, verify: bool | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> SbomListingReport
List and verify the SBOM documents attached to a package (C-014).
A read — not mutating. Exits 0 even when candidates were refused;
check summary.status, not the exit code, for a
"partial_failure" listing.
verify gates the same way install/pull's does (C-008): ocx's
default is on, but the gate only fires when a [[trust.policy]]
covers the package. verify=True against an uncovered package is a
documented no-op, not enforcement.
ocx's --output mode is not wrapped: it writes the raw predicate
bytes and prints no listing at all, so there is no report for a
typed method to return. Reach it through
ocx.invoke(["package", "sbom", "--output", "-", str(ref)]), whose
stdout the SDK captures.
| PARAMETER | DESCRIPTION |
|---|---|
ref
|
The package reference to list SBOMs for.
TYPE:
|
platform
|
Restrict to one platform's SBOM.
TYPE:
|
summary
|
Also parse each entry as CycloneDX (1.5-1.7 only) and
report its component counts on
TYPE:
|
predicate_type
|
Restrict to this predicate type — ocx's
TYPE:
|
certificate_identity
|
The pinned keyless identity, for
verifying attached signatures. Required together with
TYPE:
|
certificate_oidc_issuer
|
The pinned keyless OIDC issuer.
TYPE:
|
key
|
A key reference, for key-based verification.
TYPE:
|
signature_format
|
Restrict to one signature format.
TYPE:
|
sigstore_trusted_root
|
A non-default Sigstore trusted root bundle.
TYPE:
|
rekor_url
|
A non-default Rekor instance.
TYPE:
|
no_cache
|
Skip ocx's verification cache.
TYPE:
|
verify
|
Verify attached signatures.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
SbomListingReport
|
The summary, the listed entries, and anything refused. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
The identity pair is incomplete or combined with
|
Source code in src/ocx_sdk/_client.py
2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 | |
copy
¶
copy(source: PackageLike, *, to: str | None = None, identifier: str | None = None, platforms: Iterable[str] = (), cascade: bool = False, keep_tag: bool | None = None, referrers: bool | None = None, description: bool = False, annotations: Mapping[str, str] | None = None, dry_run: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> CopyReport
Copy a package from one location to another, server-side (C-015).
mutating=not dry_run (D5): copy(dry_run=True) writes nothing
and is exactly the read a transient registry blip should retry, so
a flat True would wrongly disable retry for it. dry_run=True
reports status="planned" rather than describing a copy that
already happened.
Non-empty sidecar_conflicts on the result means the target
already had different content under a sidecar tag copy would have
written — that call exits 65 and raises. Recover the report,
conflicts included, with partial_report(err) and
CopyReport.from_json (D10).
to/identifier is mutual exclusion, not xor: giving neither
is a legal invocation — ocx falls back to the configured default
registry, keeping source's repository and tag. Only giving both
is refused.
A digest-form source with no tag needs identifier (there is no
tag to keep at the target otherwise) and needs exactly one entry in
platforms (there is no single-platform default to fall back on).
Not guarded here, because it would take a second identifier parser:
ocx refuses a target that carries no tag, whichever route
produced it (package_copy.rs:110) — so a tagless source with no
identifier, or a tagless identifier, exits 64. Spell the tag out
at whichever end names the target.
| PARAMETER | DESCRIPTION |
|---|---|
source
|
The package reference to copy.
TYPE:
|
to
|
Rewrite only the target's registry host, keeping
TYPE:
|
identifier
|
The full target reference, when the repository path
or tag changes too. Refused alongside
TYPE:
|
platforms
|
Restrict to these platforms. Omitted copies all of
them — except when
TYPE:
|
cascade
|
Also advance the rolling tags above this version at the target.
TYPE:
|
keep_tag
|
Write the
TYPE:
|
referrers
|
Copy OCI referrers-API attachments.
TYPE:
|
description
|
Also copy the source's description metadata.
TYPE:
|
annotations
|
Extra OCI annotations for the copied index.
TYPE:
|
dry_run
|
Report what would be copied without writing.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CopyReport
|
What landed at the target, including per-platform rows and |
CopyReport
|
blob transfer counts. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
Both |
DataError
|
|
Source code in src/ocx_sdk/_client.py
2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 | |
announce
¶
announce(package: str, *, tags: Iterable[str] = (), tags_file: str | Path | None = None, tags_from_registry: bool = False, refresh: bool = False, index_repo: str | None = None, forge: Forge | None = None, transport: Transport | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> AnnounceReport
Publish a package's curated tag set into the index (C-061).
Re-observes the named tags on the registry, rebuilds the index entry
and opens — or updates — a pull or merge request against the index
repository. mutating=True (D5): retries are off by default. A run
that changes nothing reports status="unchanged" and commits nothing.
Needs a forge credential: OcxConfig.forge_token (or an ambient
OCX_ANNOUNCE_TOKEN), or the job token under transport="git"
inside a GitLab job. Without one ocx exits 80 before touching the
network. HostEnv.minimal() drops the whole CI identity ladder, so a
hermetic handle has to name the token in its config.
Exactly one tag source is required and ocx enforces it (exit 64):
tags replaces the curated set, the other three add to it, and they
are mutually exclusive. Nothing is checked here — clap's usage error
is the category, and it names the rule.
ocx's --yank/--unyank/--fork/--out are not wrapped; reach them
through invoke.
| PARAMETER | DESCRIPTION |
|---|---|
package
|
The package to announce, as
TYPE:
|
tags
|
Replace the curated tag set with these. A committed tag
not named here is dropped; a reserved
TYPE:
|
tags_file
|
Add the tags listed in this file — the one
TYPE:
|
tags_from_registry
|
Add every tag the registry repository currently holds.
TYPE:
|
refresh
|
Re-observe every committed tag, picking up a digest that moved, without changing which tags are curated.
TYPE:
|
index_repo
|
The index repository, as
TYPE:
|
forge
|
Which forge hosts it. Inferred for github.com and gitlab.com; required for a self-hosted host.
TYPE:
|
transport
|
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy. Defaults to no retries.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
AnnounceReport
|
What reached the index: status, request URL, capability checks. |
| RAISES | DESCRIPTION |
|---|---|
AuthError
|
No forge credential resolved (exit 80). |
UsageError
|
No tag source, more than one, or a self-hosted
|
ForgeCapabilityUnavailableError
|
The forge refused a job-token push (exit 86). |
Source code in src/ocx_sdk/_client.py
3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 | |
claim
¶
claim(package: str, *, repository: str, owners: Iterable[str] = (), upstream_org: str | None = None, upstream_repository_url: str | None = None, upstream_disclaimer: str | None = None, index_repo: str | None = None, forge: Forge | None = None, transport: Transport | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> ClaimReport
Claim a package in the index so its tags can be announced (C-060).
Renders the package's index entry and opens a pull or merge request.
mutating=True (D5): retries are off by default. Needs the same forge
credential announce does.
A package that is already claimed is refused with exit 65 and an
error envelope — not a report, and not a distinguishable subclass:
the envelope carries no detail for it, and the SDK never classifies
by message text. An idempotent CI step therefore reads as
except DataError, with error_envelope(err) as the machine handle
on what ocx said.
ocx's --fork/--out are not wrapped; reach them through invoke.
| PARAMETER | DESCRIPTION |
|---|---|
package
|
The package to claim, as
TYPE:
|
repository
|
The physical OCI repository the bytes live in, as
TYPE:
|
owners
|
Owners as
TYPE:
|
upstream_org
|
The upstream organization a third-party package
mirrors. Anchors the other two
TYPE:
|
upstream_repository_url
|
The upstream repository, as an absolute
TYPE:
|
upstream_disclaimer
|
A disclaimer recorded on the index entry.
TYPE:
|
index_repo
|
The index repository, as
TYPE:
|
forge
|
Which forge hosts it; required for a self-hosted host.
TYPE:
|
transport
|
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy. Defaults to no retries.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ClaimReport
|
The rendered entry: status, owners, request URL, capability checks. |
| RAISES | DESCRIPTION |
|---|---|
AuthError
|
No forge credential resolved (exit 80). |
DataError
|
The package is already claimed (exit 65). |
UsageError
|
A self-hosted |
Source code in src/ocx_sdk/_client.py
3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 | |
receipt
¶
receipt(bundle: str | Path, *, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> BuildReceipt | None
Print the build receipt create wrote beside a bundle, if any.
Answers what push and test would fall back to for the flags a
caller leaves out. Local and read-only — it touches no registry — so
it keeps the session retry policy.
| PARAMETER | DESCRIPTION |
|---|---|
bundle
|
The bundle archive
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
BuildReceipt | None
|
The receipt, or |
BuildReceipt | None
|
ocx's exit 79, the ordinary state for a bundle handed over from |
BuildReceipt | None
|
elsewhere, rather than an error here. |
| RAISES | DESCRIPTION |
|---|---|
DataError
|
A receipt file that ocx cannot read (exit 65). |
Source code in src/ocx_sdk/_client.py
cascade_check
¶
cascade_check(*refs: PackageLike, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> CascadeCheckReport
Report where packages' rolling tags disagree with their versions.
Read-only: authenticates for pull only and writes nothing, so it
keeps the session retry policy. Report-then-fail: a finding makes
ocx exit 65 with the report on stdout, and that is a result here
— report.clean (the exit code's answer) says whether anything
disagreed, and the rows say what. The same code with no report is
still the failure it names.
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Packages to audit. A tag (
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CascadeCheckReport
|
One audit per package, carrying the exit code. |
| RAISES | DESCRIPTION |
|---|---|
UsageError
|
A package names a digest, or a tag that is not a version (exit 64). |
DataError
|
Exit 65 without a report — a fault, not a finding. |
Source code in src/ocx_sdk/_client.py
cascade_repair
¶
cascade_repair(*refs: PackageLike, dry_run: bool = False, announce_tags: str | Path | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> CascadeRepairReport
Re-point packages' rolling tags at the content their versions imply.
Publishes nothing new — every index it writes references content the
registry already serves. mutating=not dry_run (D5), as copy:
the preview writes nothing and keeps the session retry policy.
Report-then-fail like cascade_check: exit 65 with the report
when a finding remains — on a dry_run, having planned anything is
the finding — so report.clean is the answer, not an exception.
Repairing the registry does not update the public index. Pass
announce_tags to record the tags this run moved, then hand that
file to announce(..., tags_file=...).
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Packages to repair.
TYPE:
|
dry_run
|
Compute and report the plan without writing.
TYPE:
|
announce_tags
|
Write the rolling tags this run moved or created to this file, one per line. Takes one package per run — ocx exits 64 when it is given more.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CascadeRepairReport
|
One entry per package, carrying the exit code. |
| RAISES | DESCRIPTION |
|---|---|
UsageError
|
A package names a digest or a non-version tag, or
|
DataError
|
Exit 65 without a report. |
Source code in src/ocx_sdk/_client.py
PatchCommands
dataclass
¶
The ocx patch command group.
sync
¶
sync(*, platform: str | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> CommandResult
Refresh patch descriptors and companion packages.
Re-checks every installed package, including ones installed before patches were configured, and needs network access. Returns the raw result: no payload shape is pinned for this command yet.
| PARAMETER | DESCRIPTION |
|---|---|
platform
|
The platform to resolve against.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CommandResult
|
The exit code and whatever ocx printed. |
Source code in src/ocx_sdk/_client.py
Project
dataclass
¶
A project-tier handle: every call carries --project <file>.
Obtained from Ocx.project(path), never constructed directly. Because
the path travels explicitly on every call, no method depends on the
working directory, and an ambient OCX_PROJECT can never retarget one.
init is the exception, and only because ocx's is: it takes no flags and
writes into the working directory, so the handle sets that instead.
Example
| ATTRIBUTE | DESCRIPTION |
|---|---|
path |
The absolute project file — the
TYPE:
|
session_config |
The
TYPE:
|
session_config
property
¶
session_config: OcxConfig
The OcxConfig this handle spawns under — see Ocx.session_config.
with_config
¶
with_config(**overrides: Unpack[ConfigOverrides]) -> Project
Derive a project handle with some configuration fields replaced.
| PARAMETER | DESCRIPTION |
|---|---|
**overrides
|
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Project
|
The same project, seen through a derived |
| RAISES | DESCRIPTION |
|---|---|
TypeError
|
An override names no |
Source code in src/ocx_sdk/_client.py
init
¶
init(*, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> CommandResult
Create a minimal ocx.toml in the project directory.
The one project-tier call that carries no --project: ocx init
takes no flags and writes into the working directory, and naming a
project would ask ocx to resolve the very file the call exists to
create. This runs it with the project's directory as its cwd
instead, so the file lands where the handle points rather than
wherever the caller happens to be.
Returns the raw result: ocx pins no JSON payload for init, so there
is nothing to type yet.
| PARAMETER | DESCRIPTION |
|---|---|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CommandResult
|
The exit code and whatever ocx printed. |
Source code in src/ocx_sdk/_client.py
add
¶
add(*refs: PackageLike, group: str | None = None, pull: bool | None = None, platform: str | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> tuple[ToolRow, ...]
Add tool bindings to ocx.toml.
| PARAMETER | DESCRIPTION |
|---|---|
*refs
|
Identifiers, each optionally prefixed
TYPE:
|
group
|
The group to add to.
TYPE:
|
pull
|
Materialize the resolved packages.
TYPE:
|
platform
|
The platform to resolve against, as
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[ToolRow, ...]
|
The lock rows the call wrote. |
Source code in src/ocx_sdk/_client.py
remove
¶
remove(*names: PackageLike, group: str | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> tuple[ToolRow, ...]
Remove tool bindings from ocx.toml.
| PARAMETER | DESCRIPTION |
|---|---|
*names
|
Binding names or fully-qualified identifiers.
TYPE:
|
group
|
The group to target.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[ToolRow, ...]
|
The lock rows the call wrote — empty when nothing changed. |
Source code in src/ocx_sdk/_client.py
lock
¶
lock(*, check_only: bool = False, pull: bool | None = None, platform: str | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> tuple[ToolRow, ...] | None
Resolve declared tags to digests and write ocx.lock.
| PARAMETER | DESCRIPTION |
|---|---|
check_only
|
Verify the lock is current and write nothing — ocx's
TYPE:
|
pull
|
Materialize the resolved packages.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[ToolRow, ...] | None
|
The lock rows written, or |
tuple[ToolRow, ...] | None
|
a current lock with exit 0 and an empty body. |
Source code in src/ocx_sdk/_client.py
update
¶
update(*names: str, check_only: bool = False, groups: Iterable[str] = (), pull: bool | None = None, platform: str | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> tuple[ToolRow, ...] | None
Re-resolve declared tags against the registry.
| PARAMETER | DESCRIPTION |
|---|---|
*names
|
Binding names to advance; every other pin freezes. Omitted advances the whole file.
TYPE:
|
check_only
|
Compare the candidate lock to its predecessor and
write nothing — ocx's
TYPE:
|
groups
|
Groups to advance.
TYPE:
|
pull
|
Materialize the resolved packages.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[ToolRow, ...] | None
|
The lock rows written, or |
Source code in src/ocx_sdk/_client.py
pull
¶
pull(*, dry_run: Literal[True], groups: Iterable[str] = (), platform: str | None = None, lazy_mode: LazyMode | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> tuple[DryRunEntry, ...]
pull(*, dry_run: Literal[False] = False, groups: Iterable[str] = (), platform: str | None = None, lazy_mode: LazyMode | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> PullReport
pull(*, dry_run: bool = False, groups: Iterable[str] = (), platform: str | None = None, lazy_mode: LazyMode | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> PullReport | tuple[DryRunEntry, ...]
Pre-warm the object store from ocx.lock.
| PARAMETER | DESCRIPTION |
|---|---|
dry_run
|
Report what would be fetched without writing. Changes
the return type: ocx previews with a different upstream
report at a different JSON root, so this answers a tuple of
TYPE:
|
groups
|
Groups to restrict the pull to.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
PullReport | tuple[DryRunEntry, ...]
|
The materialized paths and any advisories — or, under |
PullReport | tuple[DryRunEntry, ...]
|
one row per package describing what a real pull would do. |
Source code in src/ocx_sdk/_client.py
status
¶
status(*, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> StatusReport
Report what ocx.toml and ocx.lock declare, resolving nothing.
A broken or stale lock is payload here, not failure: the call still exits 0 and the state shows up on the report.
| PARAMETER | DESCRIPTION |
|---|---|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
StatusReport
|
The declared toolchain and the lock's state. |
Source code in src/ocx_sdk/_client.py
inspect
¶
inspect(*names: str, groups: Iterable[str] = (), platform: str | None = None, env: Mapping[str, EnvValue] | None = None, resolve: bool = False, closure: bool = False, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> InspectReport
Inspect the toolchain's bindings and their resolution.
| PARAMETER | DESCRIPTION |
|---|---|
*names
|
Binding names to inspect. Omitted inspects everything.
TYPE:
|
groups
|
Groups to restrict to.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
env
|
Extra
TYPE:
|
resolve
|
Add the pinned identifier, digest, layers, and the resolution chain.
TYPE:
|
closure
|
Add the dependency closure, its surface, and any
conflicts. Conflicting entrypoints raise
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
InspectReport
|
The inspected packages and the composed |
Source code in src/ocx_sdk/_client.py
env
¶
env(*, groups: Iterable[str] = (), platform: str | None = None, env: Mapping[str, EnvValue] | None = None, pull: bool | None = None, lazy_mode: LazyMode | None = None, show_patches: bool = False, pinned: bool | None = None, timeout: MaybeTimeout = UNSET, retry: MaybeRetry = UNSET) -> EnvReport
Report the environment the toolchain composes.
The report carries this handle's host snapshot, so compose() stays
hermetic: a report produced under HostEnv.clean() composes against
nothing ambient unless you pass a different base.
Note that ocx's env command takes no binding names — narrow with
groups instead.
| PARAMETER | DESCRIPTION |
|---|---|
groups
|
Groups to compose. Omitted composes the default set.
TYPE:
|
platform
|
The platform to resolve against.
TYPE:
|
env
|
Extra
TYPE:
|
pull
|
Materialize missing content first.
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
show_patches
|
Include patch-contributed entries.
TYPE:
|
pinned
|
Resolve through the rendered toolchain's pinned digests
rather than following its links — ocx's
TYPE:
|
timeout
|
Seconds per attempt. Omitted takes the config's.
TYPE:
|
retry
|
Retry policy.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
EnvReport
|
The typed entries plus the binaries, entrypoints, integrations, |
EnvReport
|
and advisories envelope. |
Source code in src/ocx_sdk/_client.py
exec
¶
exec(argv: Sequence[str], *, names: Iterable[str] = (), groups: Iterable[str] = (), clean: bool = False, env: Mapping[str, EnvValue] | None = None, lazy_mode: LazyMode | None = None, pinned: bool | None = None, records_dir: str | Path | None = None, records_name: str | None = None, capture: bool = True, check: bool = True, timeout: MaybeTimeout = UNSET) -> CommandResult
Run a command inside the project's composed environment.
The child's exit code comes back byte for byte, so check=False is
how you inspect a failing build instead of catching an exception.
Child processes are never retried.
| PARAMETER | DESCRIPTION |
|---|---|
argv
|
The command and its arguments. Must not be empty.
TYPE:
|
names
|
Bindings to compose. Omitted composes the default set.
TYPE:
|
groups
|
Groups to compose.
TYPE:
|
clean
|
Strip the ambient parent environment before composing.
TYPE:
|
env
|
Extra
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
pinned
|
Resolve through the rendered toolchain's pinned digests
rather than following its links — ocx's
TYPE:
|
records_dir
|
Write an execution record — the resolved closure
and executable, captured just before the child starts —
under this directory, which must already exist (ocx warns
and skips the record otherwise).
TYPE:
|
records_name
|
The record's filename template, over
TYPE:
|
capture
|
Pipe and capture both streams.
TYPE:
|
check
|
Raise on a non-zero child exit instead of returning it.
TYPE:
|
timeout
|
Seconds for the whole run. Omitted takes the config's.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CommandResult
|
The child's exit code and, under |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
OcxProcessError
|
The child exited non-zero under |
OcxTimeoutError
|
The timeout expired. |
Source code in src/ocx_sdk/_client.py
exec_async
async
¶
exec_async(argv: Sequence[str], *, names: Iterable[str] = (), groups: Iterable[str] = (), clean: bool = False, env: Mapping[str, EnvValue] | None = None, lazy_mode: LazyMode | None = None, pinned: bool | None = None, records_dir: str | Path | None = None, records_name: str | None = None, capture: bool = True, check: bool = True, timeout: MaybeTimeout = UNSET) -> CommandResult
Run a command in the project's environment, on the event loop.
| PARAMETER | DESCRIPTION |
|---|---|
argv
|
The command and its arguments. Must not be empty.
TYPE:
|
names
|
Bindings to compose.
TYPE:
|
groups
|
Groups to compose.
TYPE:
|
clean
|
Strip the ambient parent environment before composing.
TYPE:
|
env
|
Extra
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
pinned
|
Resolve through pinned digests — see
TYPE:
|
records_dir
|
Write an execution record here — see
TYPE:
|
records_name
|
The record's filename template — see
TYPE:
|
capture
|
Pipe and capture both streams.
TYPE:
|
check
|
Raise on a non-zero child exit instead of returning it.
TYPE:
|
timeout
|
Seconds for the whole run. Omitted takes the config's.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CommandResult
|
The child's exit code and, under |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
OcxProcessError
|
The child exited non-zero under |
OcxTimeoutError
|
The timeout expired. |
Source code in src/ocx_sdk/_client.py
spawn
¶
spawn(argv: Sequence[str], *, names: Iterable[str] = (), groups: Iterable[str] = (), clean: bool = False, env: Mapping[str, EnvValue] | None = None, lazy_mode: LazyMode | None = None, pinned: bool | None = None, records_dir: str | Path | None = None, records_name: str | None = None, **popen_kw: Any) -> Popen[Any]
Start a command in the project's environment and return Popen.
| PARAMETER | DESCRIPTION |
|---|---|
argv
|
The command and its arguments. Must not be empty.
TYPE:
|
names
|
Bindings to compose.
TYPE:
|
groups
|
Groups to compose.
TYPE:
|
clean
|
Strip the ambient parent environment before composing.
TYPE:
|
env
|
Extra
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
pinned
|
Resolve through pinned digests — see
TYPE:
|
records_dir
|
Write an execution record here — see
TYPE:
|
records_name
|
The record's filename template — see
TYPE:
|
**popen_kw
|
Forwarded to
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Popen[Any]
|
The running child. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
Source code in src/ocx_sdk/_client.py
spawn_async
async
¶
spawn_async(argv: Sequence[str], *, names: Iterable[str] = (), groups: Iterable[str] = (), clean: bool = False, env: Mapping[str, EnvValue] | None = None, lazy_mode: LazyMode | None = None, pinned: bool | None = None, records_dir: str | Path | None = None, records_name: str | None = None, **popen_kw: Any) -> Process
Start a command in the project's environment, on the event loop.
| PARAMETER | DESCRIPTION |
|---|---|
argv
|
The command and its arguments. Must not be empty.
TYPE:
|
names
|
Bindings to compose.
TYPE:
|
groups
|
Groups to compose.
TYPE:
|
clean
|
Strip the ambient parent environment before composing.
TYPE:
|
env
|
Extra
TYPE:
|
lazy_mode
|
When content downloads — now, or on first use.
TYPE:
|
pinned
|
Resolve through pinned digests — see
TYPE:
|
records_dir
|
Write an execution record here — see
TYPE:
|
records_name
|
The record's filename template — see
TYPE:
|
**popen_kw
|
Forwarded to the subprocess factory.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Process
|
The running child. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
|
Source code in src/ocx_sdk/_client.py
ConfigOverrides
¶
Bases: TypedDict
The OcxConfig fields a with_config call may replace, all optional.
What makes Ocx.with_config(...) and Project.with_config(...) check
their keyword arguments instead of accepting **overrides: Any, so a
misspelled field is a type error rather than a TypeError at runtime.
Public for the same reason MaybeRetry is: a wrapper around this SDK can
forward a caller's overrides with **overrides: Unpack[ConfigOverrides]
rather than re-declaring the field list itself.
Mirrors OcxConfig field for field — a field added there and not here is
a field with_config would refuse.
Optional at the class level rather than per field: this module postpones
annotation evaluation, and a NotRequired[...] inside a string annotation
is invisible to __required_keys__, so anything introspecting the type at
runtime would be told every field was mandatory. Every field is optional
here anyway, which is exactly what total=False says.
Example
OcxConfig
dataclass
¶
OcxConfig(home: Path | None = None, offline: bool = False, frozen: bool = False, config: Path | None = None, no_config: bool = False, managed_config: str | None = None, auth: Mapping[str, Auth] = dict[str, Auth](), insecure_registries: Collection[str] | None = None, sigstore_trusted_root: str | Path | None = None, docker_config: Path | None = None, index: Path | None = None, jobs: int | None = None, log_level: LogLevel | None = None, mirrors: Mapping[str, str] | None = None, no_update_check: bool = True, no_config_refresh: bool | None = None, consent: bool = False, records_dir: Path | None = None, records_name: str | None = None, toolchain_dir: Path | None = None, forge_token: str | None = None, forge_git_token: str | None = None, forge_git_username: str | None = None, retry: RetryPolicy | None = None, timeout: float | None = None)
Policy for every ocx process a handle spawns.
Containers are snapshotted at construction — the mappings as read-only
proxies, insecure_registries as a tuple — so neither mutating the argument
afterwards nor reaching into the field can rewrite a config a handle already
holds. Derive a variant with Ocx.with_config(...)
rather than reaching for a mutation that the frozen dataclass refuses.
| ATTRIBUTE | DESCRIPTION |
|---|---|
home |
TYPE:
|
offline |
Refuse every network access.
TYPE:
|
frozen |
Refuse any lockfile change.
TYPE:
|
config |
Explicit
TYPE:
|
no_config |
Hermetic mode — drops the discovered chain and the managed
tier. Wins over
TYPE:
|
managed_config |
OCI reference of the managed config tier.
TYPE:
|
auth |
Credentials per registry, keyed lowercase. An entry wins over an
ambient
TYPE:
|
insecure_registries |
Registries reachable over plaintext HTTP.
TYPE:
|
sigstore_trusted_root |
The Sigstore trusted root to verify signatures
against, for air-gapped verification against a private root of
trust.
TYPE:
|
docker_config |
Directory for
TYPE:
|
index |
Explicit index path;
TYPE:
|
jobs |
Parallel job cap;
TYPE:
|
log_level |
ocx trace verbosity. At
TYPE:
|
mirrors |
Registry host to mirror host, serialized into
TYPE:
|
no_update_check |
Suppress ocx's update check.
TYPE:
|
no_config_refresh |
Suppress the managed-config refresh;
TYPE:
|
consent |
Let the project-tier mutators (
TYPE:
|
records_dir |
Where
TYPE:
|
records_name |
The record filename template —
TYPE:
|
toolchain_dir |
The root ocx renders project toolchains under —
TYPE:
|
forge_token |
The forge API credential
TYPE:
|
forge_git_token |
The push secret for
TYPE:
|
forge_git_username |
The username the
TYPE:
|
retry |
Retry policy for failures ocx marked transient;
TYPE:
|
timeout |
Per-attempt budget in seconds;
TYPE:
|
Example
OcxConfig().insecure_registries is None True OcxConfig(insecure_registries=()).insecure_registries ()
ComposedEnv
dataclass
¶
A merged environment, ready for a child process.
Build one with merge(); EnvReport.compose() is the caller-facing route.
The values stay off every human-readable surface: a composed environment
inherits whatever OCX_AUTH_* its base carried, and a repr is exactly
what a traceback or a pytest diff prints (CWE-532). __repr__ names the
keys and masks every value, the same shape SpawnEnv uses.
mapping
property
¶
Return the merged environment as a fresh dict.
The non-invasive form, and the documented default: pass it as
subprocess.run(..., env=...) instead of mutating the process.
activate
¶
Apply this environment to os.environ for the duration of the block.
Process-global and single-owner: it changes what every thread and every
subprocess sees, and a second, overlapping activate() raises instead
of nesting. Concurrent code passes mapping to the subprocess call.
The revert is diff-based — only the keys this environment sets are
recorded on entry and restored on exit, keys that were absent are
deleted again, and unrelated changes made inside the block survive.
It runs in finally; os._exit, execve, and SIGKILL leave no chance
to run it at all.
| RAISES | DESCRIPTION |
|---|---|
RuntimeError
|
Another |
Source code in src/ocx_sdk/_envmodel.py
AuthError
¶
AuthError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
Registry authentication or authorization failed (exit 80).
Source code in src/ocx_sdk/_errors.py
BootstrapError
¶
ChecksumMismatchError
¶
ConfigError
¶
ConfigError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
ocx's configuration is missing or invalid (exit 78).
Source code in src/ocx_sdk/_errors.py
DataError
¶
DataError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
Input or resolved data was malformed, ambiguous, or platform-mismatched (exit 65).
Source code in src/ocx_sdk/_errors.py
DirtyRcBlockError
¶
DirtyRcBlockError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
A managed-config fence carried local edits and refused to overwrite them (exit 82).
Source code in src/ocx_sdk/_errors.py
DistManifestError
¶
DownloadError
¶
ExitCode
¶
Bases: IntEnum
Exit codes ocx assigns to error categories (sysexits.h plus ocx's own).
TEMP_FAIL is the retry signal — ocx maps 429/5xx/network timeouts onto
it, while UNAVAILABLE marks a failure that retrying cannot fix.
ForgeCapabilityUnavailableError
¶
ForgeCapabilityUnavailableError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
A forge was reached and refused a write for want of a capability (exit 86).
Raised by announce/claim under --transport git when job-token push
is disabled on the index project or the publishing project is missing
from its allowlist. Distinct from 69 (the forge could not be reached at
all) and from 80 (the credential is valid here — the refusal is not on it).
Source code in src/ocx_sdk/_errors.py
IoError
¶
IoError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
A filesystem or network I/O operation failed (exit 74).
Source code in src/ocx_sdk/_errors.py
NotFoundError
¶
NotFoundError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
A package, registry, or reference does not exist (exit 79).
Covers both things ocx can fail to find: the identifier a call named, and
the project file a --project pointed at.
Source code in src/ocx_sdk/_errors.py
OcxError
¶
Bases: Exception
Base class for every error raised by ocx-sdk.
Subclasses set _hint: the next step a caller can actually take. It is
appended to the message of every error in the hierarchy.
Errors cross process boundaries intact — a ProcessPoolExecutor worker or
a pytest-xdist node has to be able to hand one back.
OcxExecutionError
¶
Bases: OcxError
Base for failures an ocx process raised — non-zero exits and timeouts.
except OcxExecutionError is the catch shape a caller usually wants: it
covers both a process that failed and one that never finished.
| ATTRIBUTE | DESCRIPTION |
|---|---|
argv |
The argv that ran, with secrets already redacted by
TYPE:
|
stderr |
Captured stderr in full; the message shows only its tail.
TYPE:
|
Source code in src/ocx_sdk/_errors.py
OcxProcessError
¶
OcxProcessError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxExecutionError
An ocx process exited non-zero.
| ATTRIBUTE | DESCRIPTION |
|---|---|
exit_code |
The exit status.
TYPE:
|
attempts |
Attempts made; greater than 1 when a retry policy was
active.
TYPE:
|
stdout |
Captured stdout in full, verbatim. Never read by
TYPE:
|
Source code in src/ocx_sdk/_errors.py
retryable
property
¶
Whether ocx called this failure transient (exit 75).
Fixed semantics, independent of any RetryPolicy: this reports what
ocx said about the failure, not whether a caller chose to retry it.
OcxTimeoutError
¶
Bases: OcxExecutionError
ocx did not finish within the timeout and the child was terminated.
| ATTRIBUTE | DESCRIPTION |
|---|---|
timeout |
The per-attempt budget, in seconds, that expired.
TYPE:
|
argv |
The argv that ran.
TYPE:
|
stderr |
Whatever stderr was captured before the child was killed.
TYPE:
|
Source code in src/ocx_sdk/_errors.py
PermissionDeniedError
¶
PermissionDeniedError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
ocx was denied access to a resource (exit 77).
Source code in src/ocx_sdk/_errors.py
PolicyBlockedError
¶
PolicyBlockedError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
ocx refused the operation under an offline or frozen policy (exit 81).
Source code in src/ocx_sdk/_errors.py
ReferrersUnsupportedError
¶
ReferrersUnsupportedError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
The registry served neither the OCI 1.1 Referrers API nor the Referrers Tag Schema fallback (exit 84).
Source code in src/ocx_sdk/_errors.py
TempFailError
¶
TempFailError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
A transient failure ocx marked as retry-safe (exit 75).
Source code in src/ocx_sdk/_errors.py
TransparencyLogUnavailableError
¶
TransparencyLogUnavailableError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
Rekor was unreachable during a signing or verification operation (exit 83).
Source code in src/ocx_sdk/_errors.py
UnavailableError
¶
UnavailableError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
A resource is unavailable and ocx classified it as non-transient (exit 69).
Source code in src/ocx_sdk/_errors.py
UnsupportedKeyBackendError
¶
UnsupportedKeyBackendError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
ocx recognized the key backend scheme but has not implemented it (exit 85).
Source code in src/ocx_sdk/_errors.py
UnsupportedPlatformError
¶
UsageError
¶
UsageError(exit_code: int, argv: Sequence[str], stderr: str = '', *, attempts: int = 1, stdout: str = '')
Bases: OcxProcessError
ocx rejected the command line (exit 64).
Source code in src/ocx_sdk/_errors.py
VersionCompatError
¶
Bases: OcxError
The discovered ocx binary is older than this SDK supports.
| ATTRIBUTE | DESCRIPTION |
|---|---|
found |
The version the binary reported.
TYPE:
|
minimum |
The oldest version this SDK is tested against.
TYPE:
|
Source code in src/ocx_sdk/_errors.py
AboutInfo
dataclass
¶
AboutInfo(version: str, registry: str, home: str, shell: str | None, platforms: tuple[str, ...] = (), libc: tuple[str, ...] = (), channel: str | None = None, commit: Mapping[str, Any] = _EMPTY, build: Mapping[str, Any] = _EMPTY, ci: Mapping[str, Any] = _EMPTY)
ocx about — the binary plus the host it is running on.
channel appears only when it was baked into the build. shell is
always on the wire and may be null (about.rs:30) — ocx detected no
shell — so it is the only one of the four leading fields that can be
None.
from_json
classmethod
¶
from_json(raw: str) -> AboutInfo
Parse ocx --format json about output.
Source code in src/ocx_sdk/_results.py
Advisory
dataclass
¶
Something ocx wants the caller to know about a composed environment.
| ATTRIBUTE | DESCRIPTION |
|---|---|
kind |
The machine discriminator to branch on, never
TYPE:
|
package |
The package the advisory is about.
TYPE:
|
message |
The human rendering of the same fact.
TYPE:
|
key |
The environment variable named, or
TYPE:
|
AnnounceReport
dataclass
¶
AnnounceReport(package: str, status: str, desc_status: str, forge: str, transport: str, credential_kind: str, push_credential_kind: str | None, branch: str | None, pull_request_url: str | None, pull_request_number: int | None, fork: str | None, written_paths: tuple[str, ...], capability_checks: tuple[CapabilityCheck, ...], reserved_tags_dropped: tuple[str, ...])
ocx package announce — what reached the index (C-061).
Payload is bare (D11). Every one of the fourteen keys is always on
the wire; the nullable ones are null rather than absent, so all are
read with _need and typed | None where upstream is Option.
| ATTRIBUTE | DESCRIPTION |
|---|---|
package |
The announced
TYPE:
|
status |
TYPE:
|
desc_status |
TYPE:
|
forge |
TYPE:
|
transport |
TYPE:
|
credential_kind |
TYPE:
|
push_credential_kind |
TYPE:
|
branch |
The announce branch, or
TYPE:
|
pull_request_url |
The request's URL, when one was opened or ensured.
TYPE:
|
pull_request_number |
Its number, likewise.
TYPE:
|
fork |
The fork the request came from, when
TYPE:
|
written_paths |
Files written under
TYPE:
|
capability_checks |
The forge probes, in
TYPE:
|
reserved_tags_dropped |
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> AnnounceReport
Parse ocx --format json package announce output.
Source code in src/ocx_sdk/_results.py
Assertion
dataclass
¶
AttestationOutcome
dataclass
¶
AttestationOutcome(status: str, referrer_digest: str | None = None, sidecar_digest: str | None = None, predicate_type: str | None = None, signed: bool | None = None, kind: str | None = None, message: str | None = None)
The attestation outcome of one push(..., sign=True) call (C-019).
push.rs:161, internally tagged on status. A bare str (the usual D8
treatment for a scalar enum) would silently drop predicate_type and
signed, so this carries every field instead, all but status
optional: succeeded populates predicate_type/signed and at least
one of referrer_digest/sidecar_digest; failed populates
kind/message.
| ATTRIBUTE | DESCRIPTION |
|---|---|
status |
TYPE:
|
referrer_digest |
The attestation's referrer-API digest, on success.
TYPE:
|
sidecar_digest |
The attestation's sidecar-tag digest, on success.
TYPE:
|
predicate_type |
The resolved predicate type URI, on success.
TYPE:
|
signed |
Whether the attestation was itself signed, on success.
TYPE:
|
kind |
The machine-branchable failure slug, on failure.
TYPE:
|
message |
Sanitized prose describing the failure, on failure.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> AttestationOutcome
Build from the decoded PushResult.attestation object.
status selects the variant, and each variant's own fields carry no
skip_serializing_if — so they are read with _need under the status
that emits them. signed matters most: reading it with .get failed
open, turning "nothing vouches for this document" into None.
Source code in src/ocx_sdk/_results.py
AttestationReport
dataclass
¶
AttestationReport(identifier: str, platform: str, subject_digest: str, predicate_type: str, signed: bool, transparency_log_index: int | None, bundle_digest: str | None = None, referrer_digest: str | None = None, sidecar_digest: str | None = None, certificate_identity: str | None = None, certificate_oidc_issuer: str | None = None, key_backend: str | None = None, public_key_hint: str | None = None)
ocx package attest on a single reference — no tag sweep (C-013).
Payload is enveloped (D11): from_json unwraps data. Flat,
thirteen fields; per D7's field-order rule the seven optionals move to
the end even though upstream interleaves public_key_hint earlier.
| ATTRIBUTE | DESCRIPTION |
|---|---|
identifier |
The identifier that was attested.
TYPE:
|
platform |
The attested platform.
TYPE:
|
subject_digest |
The manifest digest the attestation covers.
TYPE:
|
predicate_type |
The resolved predicate type URI — not the
TYPE:
|
signed |
Whether the attestation itself was signed.
TYPE:
|
transparency_log_index |
The Rekor entry index. Always present in the
JSON, but
TYPE:
|
bundle_digest |
Digest of the attestation bundle, when produced.
TYPE:
|
referrer_digest |
Digest under the OCI referrers API, when attached that way.
TYPE:
|
sidecar_digest |
Digest of the sidecar tag, when attached that way.
TYPE:
|
certificate_identity |
The Fulcio certificate's identity, for keyless signing.
TYPE:
|
certificate_oidc_issuer |
The Fulcio certificate's OIDC issuer, for keyless signing.
TYPE:
|
key_backend |
Which key backend produced the signature, carried as
raw
TYPE:
|
public_key_hint |
A hint identifying the verifying key, when supplied.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> AttestationReport
Build from a decoded attest report.
Used both for the envelope's data (a bare attest) and, through
C-017's row-parser seam, for one SweptTagReport.report row of a
swept attest.
Source code in src/ocx_sdk/_results.py
from_json
classmethod
¶
from_json(raw: str) -> AttestationReport
BlobSummary
dataclass
¶
Blob transfer counts for one copy (C-015, package_copy.rs:140-147).
Not push's layers — that is a different struct (LayerCounts,
oci/client.rs:75-84) with a different field set,
{mounted, uploaded, verified}. Copy tracks transfer method including
blobs that needed no transfer at all; push tracks mount/upload/verify-
by-digest. Reusing push's shape here would look for a verified key
that copy never sends and silently drop present — the D7 failure
class this module exists to avoid.
| ATTRIBUTE | DESCRIPTION |
|---|---|
present |
Blobs already present at the target — no transfer needed.
TYPE:
|
mounted |
Blobs mounted from another repository without a re-upload.
TYPE:
|
uploaded |
Blobs actually transferred.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> BlobSummary
Build from the decoded blobs object.
Source code in src/ocx_sdk/_results.py
BuildReceipt
dataclass
¶
The <bundle-stem>-receipt.json sidecar ocx package create writes.
ocx package receipt <bundle> prints what create was told — the
platform it resolved against and the identifier the bundle will publish
under — so push and test need not restate either. Both keys are
absent when the build recorded neither, never null, so both are read
with .get.
The receipt file itself (<stem>-receipt.json, build_receipt.rs) is
ocx's; this SDK never reads it directly. Its format version stays behind
the command, which answers exit 65 for a file it cannot read and exit 79
for a bundle with no receipt beside it.
| ATTRIBUTE | DESCRIPTION |
|---|---|
platform |
The
TYPE:
|
identifier |
The
TYPE:
|
ref
property
¶
ref: PackageRef | None
The recorded identifier as a PackageRef, or None when none was recorded.
from_json
classmethod
¶
from_json(raw: str) -> BuildReceipt
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> BuildReceipt
Candidate
dataclass
¶
Candidate(digest: str, pinned: str, platform: str, media_type: str | None = None, size: int | None = None)
One platform's manifest for a package, as inspect lists it.
media_type and size are present on the package inspect tier only;
the toolchain tier omits them.
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> Candidate
Build from one decoded entry of a package's candidates array.
Source code in src/ocx_sdk/_results.py
CapabilityCheck
dataclass
¶
One forge capability announce/claim probed before writing.
| ATTRIBUTE | DESCRIPTION |
|---|---|
name |
The capability —
TYPE:
|
status |
What the probe found:
TYPE:
|
detail |
What the probe saw, when it recorded anything. Always on the
wire,
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> CapabilityCheck
Build from one decoded capability_checks entry.
Source code in src/ocx_sdk/_results.py
CascadeCheckReport
dataclass
¶
CascadeCheckReport(reports: tuple[CascadeReport, ...], exit_code: int = 0)
ocx package cascade check — one audit per package, in input order.
Report-then-fail: a finding makes the process exit 65 with this
document on stdout, so the client tolerates that code and hands the
report back as a result (tolerated_report). exit_code is the process's
own, carried so a caller can branch without re-deriving it from the rows.
| ATTRIBUTE | DESCRIPTION |
|---|---|
reports |
One entry per package audited.
TYPE:
|
exit_code |
TYPE:
|
from_json
classmethod
¶
from_json(raw: str, *, exit_code: int = 0) -> CascadeCheckReport
Parse ocx --format json package cascade check output.
| PARAMETER | DESCRIPTION |
|---|---|
raw
|
Captured stdout.
TYPE:
|
exit_code
|
The process's exit status, carried onto the result.
TYPE:
|
Source code in src/ocx_sdk/_results.py
CascadeRepairReport
dataclass
¶
CascadeRepairReport(entries: tuple[RepairEntry, ...], dry_run: bool, announce_tags_path: str | None, exit_code: int = 0)
ocx package cascade repair — what was re-pointed, or would be.
Report-then-fail like check: exit 65 with this document when a
finding remains — including on a dry_run, where "planned anything"
is the finding — so exit_code rather than an exception says whether
the registry now agrees with itself.
| ATTRIBUTE | DESCRIPTION |
|---|---|
entries |
One entry per package, in input order.
TYPE:
|
dry_run |
TYPE:
|
announce_tags_path |
Where
TYPE:
|
exit_code |
TYPE:
|
from_json
classmethod
¶
from_json(raw: str, *, exit_code: int = 0) -> CascadeRepairReport
Parse ocx --format json package cascade repair output.
| PARAMETER | DESCRIPTION |
|---|---|
raw
|
Captured stdout.
TYPE:
|
exit_code
|
The process's exit status, carried onto the result.
TYPE:
|
Source code in src/ocx_sdk/_results.py
CascadeReport
dataclass
¶
CascadeReport(identifier: str, logical: str | None, aliases: Mapping[str, Mapping[str, Any]], rows: tuple[SlotRow, ...], index_findings: tuple[IndexFinding, ...], ignored_tags: tuple[str, ...], unrepairable: tuple[Mapping[str, Any], ...])
One package's rolling-tag audit — the check document, and the report inside a repair entry.
First-cut depth: the rows, the index findings and the tag lists are
typed; aliases and unrepairable are carried as opaque mappings
(Integration.payload's precedent) until a consumer needs their fields.
| ATTRIBUTE | DESCRIPTION |
|---|---|
identifier |
The physical repository the graph was read from.
TYPE:
|
logical |
The logical name the caller gave, when it differed.
TYPE:
|
aliases |
Rolling tag to its alias state (
TYPE:
|
rows |
One slot per (rolling tag, platform).
TYPE:
|
index_findings |
Public-index disagreements; empty off
TYPE:
|
ignored_tags |
Tags the audit skipped — the keep tags among them.
TYPE:
|
unrepairable |
Findings
TYPE:
|
clean
property
¶
Whether nothing disagrees: every row ok, no index finding, nothing unrepairable.
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> CascadeReport
Build from one decoded reports entry (or a repair entry's report).
Source code in src/ocx_sdk/_results.py
ClaimOwner
dataclass
¶
One forge account on a claim report, as author or owner.
| ATTRIBUTE | DESCRIPTION |
|---|---|
login |
The forge's canonical login spelling.
TYPE:
|
id |
The forge's immutable numeric account id.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> ClaimOwner
Build from a decoded author or owners entry.
ClaimReport
dataclass
¶
ClaimReport(package: str, name: str, status: str, forge: str, transport: str, credential_kind: str, push_credential_kind: str | None, author: ClaimOwner | None, author_identity_source: str | None, owners: tuple[ClaimOwner, ...], owner_identity_source: str, branch: str, pull_request_url: str | None, pull_request_number: int | None, fork: str | None, written_paths: tuple[str, ...], capability_checks: tuple[CapabilityCheck, ...])
ocx package claim — the index entry a claim rendered (C-060).
Payload is bare (D11), seventeen keys, every one always on the wire.
A package that is already claimed never produces this: ocx exits 65 with
an error envelope instead, which error_envelope(err) recovers.
| ATTRIBUTE | DESCRIPTION |
|---|---|
package |
The claimed
TYPE:
|
name |
The logical name written into the root.
TYPE:
|
status |
TYPE:
|
forge |
TYPE:
|
transport |
TYPE:
|
credential_kind |
TYPE:
|
push_credential_kind |
TYPE:
|
author |
The identity that authored the request, or
TYPE:
|
author_identity_source |
TYPE:
|
owners |
The recorded owners, in order.
TYPE:
|
owner_identity_source |
TYPE:
|
branch |
The claim branch.
TYPE:
|
pull_request_url |
The request's URL, when one was opened.
TYPE:
|
pull_request_number |
Its number, likewise.
TYPE:
|
fork |
The fork the request came from, when
TYPE:
|
written_paths |
Files written under
TYPE:
|
capability_checks |
The forge probes, in
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> ClaimReport
Parse ocx --format json package claim output.
Source code in src/ocx_sdk/_results.py
CleanEntry
dataclass
¶
One thing ocx clean removed, or would remove.
| ATTRIBUTE | DESCRIPTION |
|---|---|
kind |
TYPE:
|
dry_run |
Whether this was a preview.
TYPE:
|
path |
What was (or would be) removed.
TYPE:
|
held_by |
Project
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> CleanEntry
Build from one decoded array entry.
Source code in src/ocx_sdk/_results.py
CommandResult
dataclass
¶
The outcome of one ocx process, before any typing.
What invoke() returns and what every typed method is built on.
| ATTRIBUTE | DESCRIPTION |
|---|---|
argv |
The argv that ran, with secrets already redacted by
TYPE:
|
exit_code |
The exit status.
TYPE:
|
stdout |
Raw stdout — JSON text for a
TYPE:
|
stderr |
Captured stderr in full, redacted.
TYPE:
|
ConfigSetupReport
dataclass
¶
ocx config setup — the managed_config block of self setup's report.
ocx wraps the block in an envelope; the SDK flattens it, because the
envelope has exactly one key and a ConfigSetupReport.managed_config.status
chain says nothing .status does not.
| ATTRIBUTE | DESCRIPTION |
|---|---|
status |
What the run did or would do, e.g.
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> ConfigSetupReport
Parse ocx --format json config setup output.
Source code in src/ocx_sdk/_results.py
ConfigUpdateReport
dataclass
¶
ConfigUpdateReport(status: str, source: str | None = None, digest: str | None = None, policy: str | None = None, tag: str | None = None, fetched_at: str | None = None, paused_until: str | None = None, pinned: str | None = None, drift: Any = None, kill_switches: tuple[str, ...] = ())
ocx config update — the managed-config tier's state.
status is the only field ocx always emits; the rest describe a tier that
is actually configured, and a not_configured answer carries none of them.
| ATTRIBUTE | DESCRIPTION |
|---|---|
status |
TYPE:
|
source |
The OCI reference the snapshot follows.
TYPE:
|
digest |
The snapshot's digest.
TYPE:
|
policy |
TYPE:
|
tag |
The tag the source resolved to.
TYPE:
|
fetched_at |
When the snapshot was fetched.
TYPE:
|
paused_until |
When an active pause expires.
TYPE:
|
pinned |
The version a pin holds it at.
TYPE:
|
drift |
How the on-disk state diverged, carried untyped.
TYPE:
|
kill_switches |
Kill switches the snapshot activates.
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> ConfigUpdateReport
Parse ocx --format json config update output.
Source code in src/ocx_sdk/_results.py
CopiedPlatformRow
dataclass
¶
One platform copy carried over to the target (C-015, package_copy.rs:128-136).
| ATTRIBUTE | DESCRIPTION |
|---|---|
platform |
The platform this row describes.
TYPE:
|
digest |
The platform manifest's digest at the target.
TYPE:
|
disposition |
What happened to this platform's manifest at the
target — a D8 kebab-case scalar enum:
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> CopiedPlatformRow
Build from one decoded entry of CopyReport.platforms.
Source code in src/ocx_sdk/_results.py
CopyReport
dataclass
¶
CopyReport(source: str, target: str, status: str, platforms: tuple[CopiedPlatformRow, ...], cascade_tags_written: tuple[str, ...], keep_tags_written: tuple[str, ...], referrers_copied: int, sidecars_copied: int, sidecar_conflicts: tuple[str, ...], blobs: BlobSummary, description: str | None)
ocx package copy (C-015).
Payload is bare (D11) — from_json reads the JSON root directly,
no envelope to unwrap. Non-empty sidecar_conflicts means exit 65 and
therefore raises; because the payload is bare, partial_report(err)
returns the same document this from_json parses, so the conflict list
is readable from the failure itself.
All eleven fields verified always present against package_copy.rs:97-124
— no skip_serializing_if anywhere on this struct, description
included (upstream comment: "serializes as null, so the key is always
there to branch on"). No D7 reordering needed: this is upstream's own
field order, verbatim.
| ATTRIBUTE | DESCRIPTION |
|---|---|
source |
The identifier that was copied.
TYPE:
|
target |
Where it was copied to.
TYPE:
|
status |
What happened, e.g.
TYPE:
|
platforms |
One row per platform manifest carried over.
TYPE:
|
cascade_tags_written |
Cascading tags updated at the target.
TYPE:
|
keep_tags_written |
TYPE:
|
referrers_copied |
Referrer-API attachments carried over.
TYPE:
|
sidecars_copied |
Sidecar-tag attachments carried over.
TYPE:
|
sidecar_conflicts |
Sidecar tags that already existed at the target with different content. Non-empty means the call raised.
TYPE:
|
blobs |
Blob transfer counts.
TYPE:
|
description |
A
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> CopyReport
Parse ocx --format json package copy output.
Source code in src/ocx_sdk/_results.py
DepNode
dataclass
¶
DepNode(identifier: str, repeated: bool = False, visibility: str | None = None, dependencies: tuple[Mapping[str, Any], ...] = ())
One node of the package deps tree.
| ATTRIBUTE | DESCRIPTION |
|---|---|
identifier |
The pinned identifier.
TYPE:
|
repeated |
This node already appeared elsewhere in the tree; its children are not repeated under it.
TYPE:
|
visibility |
How the parent exposes it, when the parent says.
TYPE:
|
dependencies |
Child nodes, carried untyped. The only probe available
had no dependencies, so the populated child shape is UNCONFIRMED —
re-model this as
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> DepNode
Build from one decoded node of the roots array.
Source code in src/ocx_sdk/_results.py
DepsReport
dataclass
¶
DepsReport(roots: tuple[DepNode, ...] = ())
ocx package deps — a {"roots": [...]} wrapper, not a bare array.
from_json
classmethod
¶
from_json(raw: str) -> DepsReport
Parse ocx --format json package deps output.
Source code in src/ocx_sdk/_results.py
DryRunEntry
dataclass
¶
One row of pull(dry_run=True) — what a real pull would do to a package.
pull_dry_run.rs:76 serializes the preview as a bare root array, so
there is no envelope object and no wrapper struct here: the rows are the
document (D11).
| ATTRIBUTE | DESCRIPTION |
|---|---|
package |
The pinned identifier the row is about.
TYPE:
|
status |
TYPE:
|
path |
Where the package already sits, or
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> DryRunEntry
Build from one decoded array entry.
Source code in src/ocx_sdk/_results.py
EnvEntry
dataclass
¶
One [env] contribution from ocx env.
| ATTRIBUTE | DESCRIPTION |
|---|---|
key |
The variable name.
TYPE:
|
type |
How the value folds onto the parent environment.
TYPE:
|
value |
The contribution, verbatim. ocx has already resolved its own
TYPE:
|
separator |
The separator a
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> EnvEntry
Build from one decoded entry of an entries array.
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
The entry declares a type this SDK cannot fold. |
Source code in src/ocx_sdk/_results.py
EnvReport
dataclass
¶
EnvReport(entries: tuple[EnvEntry, ...] = (), binaries: tuple[PackageBinding, ...] = (), entrypoints: tuple[PackageBinding, ...] = (), integrations: tuple[Integration, ...] = (), advisories: tuple[Advisory, ...] = (), _base: Mapping[str, str] = _EMPTY)
ocx env and ocx package env — the same five-array envelope, both tiers.
Iterating the report iterates entries: composing an environment is what
it is for, and the other four arrays are description.
| ATTRIBUTE | DESCRIPTION |
|---|---|
entries |
The
TYPE:
|
binaries |
Executables the packages put on PATH. Pre-1.0, may break.
TYPE:
|
entrypoints |
Named entrypoints the packages declare. Pre-1.0, may break.
TYPE:
|
integrations |
Tool integrations, payloads untyped. Pre-1.0, may break.
TYPE:
|
advisories |
Warnings about the composition. Pre-1.0, may break.
TYPE:
|
The four non-entry arrays carry ocx's package which-style caveat: they
are not on ocx's durable-anchor list, so their shape may change in a minor
release. entries is the part the SDK depends on.
Example
compose
¶
compose(base: Mapping[str, str] | None = None) -> ComposedEnv
Fold these entries onto an environment.
| PARAMETER | DESCRIPTION |
|---|---|
base
|
What to fold onto. Defaults to the environment the producing call ran under, so composing a report from a hermetic handle stays hermetic.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ComposedEnv
|
The merged environment. |
ComposedEnv
|
|
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
Two list contributions to one key disagree about the
separator, or a value is edged by the one it folds with
( |
Source code in src/ocx_sdk/_results.py
from_json
classmethod
¶
from_json(raw: str, *, base: Mapping[str, str] = _EMPTY) -> EnvReport
Parse ocx --format json env (or package env) output.
| PARAMETER | DESCRIPTION |
|---|---|
raw
|
Captured stdout.
TYPE:
|
base
|
The environment the call ran under, carried for
TYPE:
|
Source code in src/ocx_sdk/_results.py
ErrorEnvelope
dataclass
¶
ErrorEnvelope(schema_version: int, command: str, exit_code: int, kind: str, message: str, detail: str | None = None, remediation: str | None = None, context: Mapping[str, Any] = _EMPTY)
The structured failure ocx prints under --format json (C-S1-1).
{schema_version, command, exit_code, error: {kind, detail?, message,
remediation?, context}} — a contract frozen separately from the reports
schema, and printed on stdout only when the failing command wrote no
report of its own. error_envelope(err) is how a caller reaches it.
The exit code is still the category (_errors): kind restates it as
ocx's own vocabulary, and detail — when present — is the fine-grained
slug to branch on. message is prose, free to be reworded.
| ATTRIBUTE | DESCRIPTION |
|---|---|
schema_version |
The envelope's own version;
TYPE:
|
command |
The canonical command string, e.g.
TYPE:
|
exit_code |
The exit status the process returned.
TYPE:
|
kind |
The coarse category, snake_case (
TYPE:
|
message |
The outermost message of the error chain.
TYPE:
|
detail |
The fine-grained variant slug, when ocx assigned one.
TYPE:
|
remediation |
A remediation hint. Reserved upstream and never emitted by a 0.6 binary; carried so a consumer treating it as optional keeps working when it appears.
TYPE:
|
context |
Structured context (identifiers, digests, URLs), untyped.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> ErrorEnvelope
Build from a decoded envelope, reading across its two levels.
Source code in src/ocx_sdk/_results.py
GroupStatus
dataclass
¶
GroupStatus(tools: Mapping[str, ToolBinding] = _EMPTY, env: Mapping[str, Mapping[str, Any]] = _EMPTY)
One group of ocx status.
| ATTRIBUTE | DESCRIPTION |
|---|---|
tools |
Binding name to its binding state.
TYPE:
|
env |
The group's
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> GroupStatus
Build from one decoded entry of the groups object.
Source code in src/ocx_sdk/_results.py
IndexFinding
dataclass
¶
Where the public index disagrees with the registry about an alias.
Internally tagged on finding: stale carries the two digests, and
not-committed carries only the tag. Reported for ocx.sh/... packages
alone, and never fixed by repair — announcing the tag is what fixes it.
| ATTRIBUTE | DESCRIPTION |
|---|---|
tag |
The rolling tag.
TYPE:
|
finding |
TYPE:
|
committed |
The digest the index committed, under
TYPE:
|
live |
The digest the alias points at today, under
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> IndexFinding
Build from one decoded index_findings entry.
Source code in src/ocx_sdk/_results.py
InspectedPackage
dataclass
¶
InspectedPackage(name: str, identifier: str, candidates: tuple[Candidate, ...] = (), pinned_identifier: str | None = None, pinned_digest: str | None = None, platform: Mapping[str, Any] | None = None, metadata: Mapping[str, Any] | None = None, layers: tuple[Mapping[str, Any], ...] = (), resolution: Mapping[str, Any] | None = None, closure: Mapping[str, Any] | None = None)
One package row of inspect or package inspect.
name reads differently per tier: a binding name at the toolchain tier,
the full requested identifier at the package tier.
Everything from pinned_identifier down appears only under --resolve or
--closure. resolution and closure stay mappings: both are deep trees
whose interesting parts (closure.surface, closure.conflicts) are still
moving upstream, and modelling a tree we would have to re-model on the next
ocx release buys nothing v0.1 needs.
| ATTRIBUTE | DESCRIPTION |
|---|---|
name |
Binding name, or the requested identifier at the package tier.
TYPE:
|
identifier |
The identifier as requested.
TYPE:
|
candidates |
One entry per platform ocx found.
TYPE:
|
pinned_identifier |
TYPE:
|
pinned_digest |
TYPE:
|
platform |
TYPE:
|
metadata |
TYPE:
|
layers |
TYPE:
|
resolution |
TYPE:
|
closure |
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> InspectedPackage
Build from one decoded entry of the packages array.
Source code in src/ocx_sdk/_results.py
InspectReport
dataclass
¶
InspectReport(packages: tuple[InspectedPackage, ...] = (), env: tuple[EnvEntry, ...] = (), platform: str | None = None)
ocx inspect and ocx package inspect — the same envelope, both tiers.
| ATTRIBUTE | DESCRIPTION |
|---|---|
packages |
One row per requested package or declared binding.
TYPE:
|
env |
The
TYPE:
|
platform |
The platform resolution ran against, under
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> InspectReport
Parse ocx --format json inspect (or package inspect) output.
Source code in src/ocx_sdk/_results.py
InstalledPackage
dataclass
¶
One package package install or package select put in place.
| ATTRIBUTE | DESCRIPTION |
|---|---|
identifier |
The pinned identifier,
TYPE:
|
path |
The symlink that now points at it —
TYPE:
|
metadata |
The package's
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> InstalledPackage
Build from one decoded value of the keyed object.
Source code in src/ocx_sdk/_results.py
InstallReport
dataclass
¶
InstallReport(packages: Mapping[str, InstalledPackage] = _EMPTY)
ocx package install and ocx package select — the same keyed object.
Keys are the identifiers as given; the values carry the pinned form. That asymmetry is the point: a caller can look up what it asked for without knowing what it resolved to.
| ATTRIBUTE | DESCRIPTION |
|---|---|
packages |
Requested identifier to what got installed.
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> InstallReport
Parse ocx --format json package install (or select) output.
Source code in src/ocx_sdk/_results.py
Integration
dataclass
¶
A tool integration a package declares, with its payload carried untyped.
| ATTRIBUTE | DESCRIPTION |
|---|---|
namespace |
The integration namespace the package declares.
TYPE:
|
package |
The declaring package, or
TYPE:
|
payload |
The interpolated payload, uninterpreted.
TYPE:
|
ref
property
¶
ref: PackageRef | None
The declaring package, as a PackageRef, or None when unattributed.
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> Integration
Build from one decoded integrations entry.
Source code in src/ocx_sdk/_results.py
ListingSummary
dataclass
¶
ListingSummary(status: str, verification: str, exit_code: int, total: int, verified: int, unverified: int, refused: int)
The summary block of an SbomListingReport (C-014).
sbom.rs:75. All seven fields are always present.
| ATTRIBUTE | DESCRIPTION |
|---|---|
status |
TYPE:
|
verification |
TYPE:
|
exit_code |
The process's own exit code.
TYPE:
|
total |
Candidates examined.
TYPE:
|
verified |
Candidates whose signature verified.
TYPE:
|
unverified |
Candidates attached without a verifying signature.
TYPE:
|
refused |
Candidates rejected outright — see
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> ListingSummary
Build from the decoded summary object.
Source code in src/ocx_sdk/_results.py
LockStatus
dataclass
¶
LockStatus(present: bool = False, current: bool = False, lock_version: int | None = None, declaration_hash: str | None = None, declaration_hash_expected: str | None = None, generated_by: str | None = None, generated_at: str | None = None, error: str | None = None)
The lock block of ocx status.
A lock file that is broken or unreadable is payload, not failure: ocx
still exits 0 and reports error here. Callers check current, not the
exit code.
| ATTRIBUTE | DESCRIPTION |
|---|---|
present |
A lock file exists.
TYPE:
|
current |
It matches the declaration it was generated from.
TYPE:
|
lock_version |
Lock file format version.
TYPE:
|
declaration_hash |
Hash recorded in the lock file.
TYPE:
|
declaration_hash_expected |
Hash of the declaration as it reads now.
Differs from
TYPE:
|
generated_by |
The ocx version that wrote the lock file.
TYPE:
|
generated_at |
When it did, as ocx spelled it.
TYPE:
|
error |
Why the lock file could not be read, when it could not be.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> LockStatus
Build from the decoded lock object.
Source code in src/ocx_sdk/_results.py
LoginResult
dataclass
¶
ocx login — which registry, as whom.
LogoutResult
dataclass
¶
ocx logout — which registry. Always succeeds, even if nothing was stored.
from_json
classmethod
¶
from_json(raw: str) -> LogoutResult
PackageBinding
dataclass
¶
A name a package provides — the row shape binaries and entrypoints share.
| ATTRIBUTE | DESCRIPTION |
|---|---|
name |
The binary or entrypoint name the package claims.
TYPE:
|
package |
The package that claimed it, or
TYPE:
|
ref
property
¶
ref: PackageRef | None
The providing package, as a PackageRef, or None when unattributed.
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> PackageBinding
Build from one decoded binaries or entrypoints entry.
PackageDescription
dataclass
¶
One package's description metadata, from package description pull (C-021, D4).
api/data/package_description.rs's Inner — every field is optional
upstream, but carries no skip_serializing_if, so all three keys are
always present and null when unset — not absent-when-empty. D7
therefore wants str | None with no Python default, parsed via _need,
not data.get(). An all-None instance is still a real, valid value
either way: it is distinct from the None entry InfoResult uses when
the registry holds no description at all.
| ATTRIBUTE | DESCRIPTION |
|---|---|
title |
The package's display title.
TYPE:
|
description |
Its prose description.
TYPE:
|
keywords |
A single delimited string upstream, not a list — do not split it into a collection here.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> PackageDescription
Build from one non-null value of package description pull's keyed object.
Source code in src/ocx_sdk/_results.py
PullReport
dataclass
¶
PullReport(packages: Mapping[str, WhichResult] = _EMPTY, advisories: tuple[Mapping[str, Any], ...] = ())
ocx pull at the project tier — paths plus advisories.
The wire object mixes both: identifiers key {path, kind} values, and a
sibling advisories key sits among them. An identifier is always at least
<repo>/<name>, so it can never collide with that key.
| ATTRIBUTE | DESCRIPTION |
|---|---|
packages |
Pinned identifier to where it landed.
TYPE:
|
advisories |
Warnings, carried untyped — no probe has seen a populated
one, and
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> PullReport
Parse ocx --format json pull output.
Source code in src/ocx_sdk/_results.py
PushResult
dataclass
¶
PushResult(identifier: str, status: str, manifest_digest: str, cascade_tags_written: tuple[str, ...], keep_tags_written: tuple[str, ...], layers: Mapping[str, Any], platform_digests: Mapping[str, str] = _EMPTY, signatures: tuple[SignedPlatformReport, ...] = (), attestation: AttestationOutcome | None = None)
ocx package push — what landed in the registry.
| ATTRIBUTE | DESCRIPTION |
|---|---|
identifier |
What was pushed.
TYPE:
|
status |
What happened, e.g.
TYPE:
|
manifest_digest |
Digest of the manifest that was written.
TYPE:
|
cascade_tags_written |
Cascading tags updated by the push.
TYPE:
|
keep_tags_written |
The
TYPE:
|
layers |
Layer counts (
TYPE:
|
platform_digests |
Manifest digest per pushed platform (C-005). Absent-when-unused (D7).
TYPE:
|
signatures |
One row per platform's signing outcome, when
TYPE:
|
attestation |
The push's attestation outcome, when one was requested (C-005, C-019). Absent-when-unused (D7).
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> PushResult
Parse ocx --format json package push output.
The payload is bare (D11) — the report sits at the JSON root, with
no envelope to unwrap. A push that lands and then fails to sign exits
non-zero carrying this same document, so partial_report(err) feeds
straight back into this parser (D10, C-009).
Source code in src/ocx_sdk/_results.py
RefusedEntry
dataclass
¶
One candidate sbom examined and rejected (C-014).
All three fields always present (sbom.rs:192-205).
| ATTRIBUTE | DESCRIPTION |
|---|---|
referrer_digest |
The rejected candidate's own digest.
TYPE:
|
reason |
English prose explaining the refusal — free to be reworded
upstream (PKG-25); branch on
TYPE:
|
reason_kind |
The frozen, machine-branchable slug to switch on.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> RefusedEntry
Build from one decoded entry of SbomListingReport.refused.
Source code in src/ocx_sdk/_results.py
RemovalResult
dataclass
¶
One row of package uninstall or package deselect.
Both commands return a bare array rather than a keyed object — the only two package-tier mutators that do.
| ATTRIBUTE | DESCRIPTION |
|---|---|
package |
The identifier as given.
TYPE:
|
status |
What happened, e.g.
TYPE:
|
path |
The symlink that went away, or
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> RemovalResult
Build from one decoded array entry.
Source code in src/ocx_sdk/_results.py
RepairEntry
dataclass
¶
RepairEntry(report: CascadeReport, planned: tuple[Mapping[str, Any], ...], outcomes: tuple[RepairOutcome, ...], announce_tags: tuple[str, ...])
One package's cascade repair run.
| ATTRIBUTE | DESCRIPTION |
|---|---|
report |
The audit the plan was computed from — the same shape
TYPE:
|
planned |
The alias indexes the run would write (or wrote), each
TYPE:
|
outcomes |
What happened per tag. Empty on a dry run.
TYPE:
|
announce_tags |
The rolling tags this run moved or created — the
lines
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> RepairEntry
Build from one decoded entries entry.
Source code in src/ocx_sdk/_results.py
RepairOutcome
dataclass
¶
What cascade repair did to one rolling tag.
The wire nests a WriteOutcome object under outcome, internally
tagged on its own outcome key: written (with digest, verified,
and dropped when child digests were pruned), refused (an
unrepairable finding's tag/reason/digest), raced (expected,
live) or failed (message). First-cut depth: the discriminator is
typed and the variant's fields ride along untyped.
| ATTRIBUTE | DESCRIPTION |
|---|---|
tag |
The rolling tag.
TYPE:
|
outcome |
TYPE:
|
detail |
The whole
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> RepairOutcome
Build from one decoded outcomes entry.
Source code in src/ocx_sdk/_results.py
SbomEntry
dataclass
¶
SbomEntry(predicate_type: str, verified: bool, shadowed: bool, subject_digest: str, referrer_digest: str, certificate_identity: str | None = None, certificate_oidc_issuer: str | None = None, signed_at: str | None = None, summary: SbomSummaryOut | None = None)
One SBOM document sbom listed (C-014).
Field list verified against sbom.rs:104-162.
| ATTRIBUTE | DESCRIPTION |
|---|---|
predicate_type |
The SBOM's predicate type URI (CycloneDX, SPDX, ...).
TYPE:
|
verified |
Whether a signature was verified over this document.
TYPE:
|
shadowed |
Whether a platform-level SBOM of the same
TYPE:
|
subject_digest |
The manifest digest this SBOM describes.
TYPE:
|
referrer_digest |
This SBOM document's own digest. Not always a
manifest digest — for a verified
TYPE:
|
certificate_identity |
The Fulcio certificate's identity, when
TYPE:
|
certificate_oidc_issuer |
The Fulcio certificate's OIDC issuer, when
TYPE:
|
signed_at |
When the signature was produced, as ocx spelled it, when
TYPE:
|
summary |
Component counts, when the call carried
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> SbomEntry
Build from one decoded entry of SbomListingReport.entries.
Source code in src/ocx_sdk/_results.py
SbomListingReport
dataclass
¶
SbomListingReport(summary: ListingSummary, entries: tuple[SbomEntry, ...], refused: tuple[RefusedEntry, ...])
ocx package sbom — the full listing (C-014).
Payload is enveloped (D11): from_json unwraps data. Exits 0 even
when candidates were refused — check summary.status, not the exit
code.
| ATTRIBUTE | DESCRIPTION |
|---|---|
summary |
Counts and overall status.
TYPE:
|
entries |
SBOM documents ocx listed. A plain
TYPE:
|
refused |
Candidates ocx rejected outright. Same as
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> SbomListingReport
Parse ocx --format json package sbom output (full listing).
Source code in src/ocx_sdk/_results.py
SbomSummaryOut
dataclass
¶
SbomSummaryOut(spec_version: str, component_count: int, serial_number: str | None = None, top_level_component: str | None = None)
CycloneDX component counts for one SBOM entry, under --summary (C-014, sbom.rs:166-177).
Not a second top-level shape. --summary does not change sbom's
JSON root — it populates this struct per-entry, at
SbomEntry.summary, for each entry that parsed successfully as
CycloneDX 1.5-1.7. Nothing like ListingSummary's seven fields:
sbom() needs no overload, and this is built with from_dict, never
from_json, because it never sits at a JSON root.
| ATTRIBUTE | DESCRIPTION |
|---|---|
spec_version |
The CycloneDX spec version this document declares.
TYPE:
|
component_count |
How many components the document lists.
TYPE:
|
serial_number |
The document's serial number, when it declares one.
TYPE:
|
top_level_component |
The root component's name, when the document declares one.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> SbomSummaryOut
Build from the decoded summary object of one SbomEntry.
Source code in src/ocx_sdk/_results.py
SignatureEntry
dataclass
¶
SignatureEntry(signature_format: str, discovery_method: str, key_backend: str, referrer_digest: str, certificate_identity: str | None = None, certificate_oidc_issuer: str | None = None, signed_at: str | None = None, rekor_log_index: int | None = None)
One signature verify found on the inspected object (C-012).
Field list verified against verification.rs:50-85.
| ATTRIBUTE | DESCRIPTION |
|---|---|
signature_format |
Which format this entry is, carried as raw
TYPE:
|
discovery_method |
How ocx found it — referrer API or sidecar tag,
carried as raw
TYPE:
|
key_backend |
Which key backend verified it, carried as raw
TYPE:
|
referrer_digest |
This signature's own digest. Not always a manifest digest — for a simplesigning sidecar it is a layer blob digest; feeding it to a manifest fetch 404s.
TYPE:
|
certificate_identity |
The Fulcio certificate's identity, when the signature is keyless.
TYPE:
|
certificate_oidc_issuer |
The Fulcio certificate's OIDC issuer, when the signature is keyless.
TYPE:
|
signed_at |
When the signature was produced, as ocx spelled it, when present.
TYPE:
|
rekor_log_index |
The Rekor entry index, when present. Named
differently from
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> SignatureEntry
Build from one decoded entry of VerificationReport.signatures.
Source code in src/ocx_sdk/_results.py
SignatureLegReport
dataclass
¶
SignatureLegReport(format: str, payload_digest: str | None = None, manifest_digest: str | None = None, error: str | None = None)
One signature format's outcome within a SignatureReport (C-011).
| ATTRIBUTE | DESCRIPTION |
|---|---|
format |
The signature format this leg produced —
TYPE:
|
payload_digest |
Digest of the signed payload, when this leg landed.
TYPE:
|
manifest_digest |
Digest of the manifest the signature attaches to, when this leg landed.
TYPE:
|
error |
Why this leg failed, when it did. A
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> SignatureLegReport
Build from one decoded entry of SignatureReport.legs.
Source code in src/ocx_sdk/_results.py
SignatureReport
dataclass
¶
SignatureReport(identifier: str, subject_digest: str, legs: tuple[SignatureLegReport, ...], platform: str, signer: str, certificate_identity: str, certificate_oidc_issuer: str, key_backend: str, transparency_log_index: int | None, public_key_hint: str | None = None)
ocx package sign on a single reference — no tag sweep (C-011).
Payload is enveloped (D11): from_json unwraps data via
_envelope before parsing. A --signature-format both run where one leg
lands and one fails exits non-zero carrying a full report — recover it
with partial_report(err) and this same from_json (D10); legs names
which leg died through its error field.
Per D7's field-order rule, public_key_hint moves to the end even
though upstream orders it before transparency_log_index — transcribing
that order verbatim would put a defaulted field before a required one.
| ATTRIBUTE | DESCRIPTION |
|---|---|
identifier |
The identifier that was signed.
TYPE:
|
subject_digest |
The manifest digest the signature covers.
TYPE:
|
legs |
One row per signature format requested.
TYPE:
|
platform |
The signed platform.
TYPE:
|
signer |
The signing mode label — never an identity and never a key
reference.
TYPE:
|
certificate_identity |
The Fulcio certificate's identity. Plain
TYPE:
|
certificate_oidc_issuer |
The Fulcio certificate's OIDC issuer.
Always emitted (
TYPE:
|
key_backend |
Which key backend produced the signature, carried as
raw
TYPE:
|
transparency_log_index |
The Rekor entry index. Always present in the
JSON, but
TYPE:
|
public_key_hint |
A hint identifying the verifying key, when ocx supplied one.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> SignatureReport
Build from a decoded sign report.
Used both for the envelope's data (a bare sign) and, through
C-017's row-parser seam, for one SweptTagReport.report row of a
swept sign.
Source code in src/ocx_sdk/_results.py
from_json
classmethod
¶
from_json(raw: str) -> SignatureReport
SignedPlatformReport
dataclass
¶
SignedPlatformReport(platform: str, status: str, report: SignatureReport | None = None, kind: str | None = None, message: str | None = None)
One platform's signing outcome, nested in PushResult.signatures (C-018).
push.rs:115. The three optionals are absent-when-none (D7): a
platform whose signing needed no more than the default leg carries
report alone, and kind/message populate only when that platform's
signing failed.
| ATTRIBUTE | DESCRIPTION |
|---|---|
platform |
The platform this row describes.
TYPE:
|
status |
A
TYPE:
|
report |
The platform's own
TYPE:
|
kind |
The machine-branchable failure slug, when this platform failed.
TYPE:
|
message |
Sanitized prose describing the failure, free to be reworded.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> SignedPlatformReport
Build from one decoded entry of PushResult.signatures.
Source code in src/ocx_sdk/_results.py
SlotRow
dataclass
¶
SlotRow(tag: str, platform: Mapping[str, Any], status: str, observed: str | None, expected: str | None, source: str | None, observed_source: str | None)
One (rolling tag, platform) slot cascade check examined.
| ATTRIBUTE | DESCRIPTION |
|---|---|
tag |
The rolling tag —
TYPE:
|
platform |
The OCI platform object of the slot, carried untyped: the
published schema types it as
TYPE:
|
status |
TYPE:
|
observed |
The digest the alias carries for this platform, if any.
TYPE:
|
expected |
The digest the fold expects, if any.
TYPE:
|
source |
The version the expectation was folded from, e.g.
TYPE:
|
observed_source |
The version the observed digest belongs to, or
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> SlotRow
Build from one decoded rows entry.
Source code in src/ocx_sdk/_results.py
StatusReport
dataclass
¶
StatusReport(project: str, lock: LockStatus = LockStatus(), groups: Mapping[str, GroupStatus] = _EMPTY, package_settings: Mapping[str, Mapping[str, Any]] = _EMPTY)
ocx status — the project's declaration, lock, and groups.
Exits 0 even when the lock is broken, so this struct is where a caller
learns something is wrong (lock.current, lock.error).
| ATTRIBUTE | DESCRIPTION |
|---|---|
project |
Path to the
TYPE:
|
lock |
Lock file state.
TYPE:
|
groups |
Group name to its contents.
TYPE:
|
package_settings |
Per-package settings, carried through untyped — they are ocx's configuration surface, not the SDK's.
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> StatusReport
Parse ocx --format json status output.
Source code in src/ocx_sdk/_results.py
SweepReport
dataclass
¶
SweepReport(tags: tuple[SweptTagReport, ...])
ocx package sign --tags / attest --tags (or --tags-file) (C-017, D2).
Upstream is generic (sweep.rs:152,
SweepReport<R> { tags: Vec<SweptTagReport<R>> }); this is its Python
shape for both instantiations. Carries no command or exit_code
field — both are #[serde(skip)] upstream.
Payload is enveloped (D11): the envelope's data holds
{"tags": [...]}, and its exit_code — not part of data — is the
process's own. A partially-failed sweep exits non-zero, so a failed
row usually arrives through partial_report(err) rather than a normal
return (D10); both paths parse through this same from_json.
| ATTRIBUTE | DESCRIPTION |
|---|---|
tags |
One row per swept tag. A plain
TYPE:
|
from_json
classmethod
¶
from_json(raw: str, row: Callable[[Mapping[str, Any]], _SweepRow]) -> SweepReport
Parse an enveloped sweep payload from a swept sign or attest.
| PARAMETER | DESCRIPTION |
|---|---|
raw
|
Captured stdout.
TYPE:
|
row
|
Parses each row's
TYPE:
|
Source code in src/ocx_sdk/_results.py
SweptTagReport
dataclass
¶
SweptTagReport(tag: str, status: str, report: _SweepRow | None = None, kind: str | None = None, message: str | None = None)
One tag's outcome within a SweepReport (C-017).
sweep.rs:65-89. report, kind, and message are all
absent-when-none (D7) —
#[serde(skip_serializing_if = "Option::is_none")] upstream, not
null.
report is present on a failed row too, when a
--signature-format both tag lands one leg and loses the other: hiding
the leg that landed would leave an operator re-signing what is already
published.
| ATTRIBUTE | DESCRIPTION |
|---|---|
tag |
The tag this row describes.
TYPE:
|
status |
TYPE:
|
report |
The tag's own report, when one was produced — a
TYPE:
|
kind |
The machine-branchable failure slug, when this tag failed.
TYPE:
|
message |
Sanitized prose describing the failure, free to be
reworded — the same rule
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any], row: Callable[[Mapping[str, Any]], _SweepRow]) -> SweptTagReport
Build from one decoded entry of SweepReport.tags.
| PARAMETER | DESCRIPTION |
|---|---|
data
|
The decoded row.
TYPE:
|
row
|
Parses this row's
TYPE:
|
Source code in src/ocx_sdk/_results.py
TestResult
dataclass
¶
ocx package test --script — the stable v1 envelope.
Only the --script form produces this. The trailing -- CMD form
prints the child's raw stdout verbatim, even under --format json, so
parsing that output here would either fail loudly or — worse — succeed on
a child that happened to print JSON. The client layer never routes -- CMD
output into this parser.
status decides pass or fail; assertion.kind says why a failure failed.
| ATTRIBUTE | DESCRIPTION |
|---|---|
status |
TYPE:
|
run |
What the tested command did, or
TYPE:
|
assertion |
The assertion that fired, or
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> TestResult
Parse ocx --format json package test --script ... output.
Source code in src/ocx_sdk/_results.py
TestRun
dataclass
¶
What the tested command actually did.
| ATTRIBUTE | DESCRIPTION |
|---|---|
exit_code |
The command's exit status.
TYPE:
|
stdout |
Its stdout, truncated if
TYPE:
|
stderr |
Its stderr, same.
TYPE:
|
duration_ms |
Wall time in milliseconds.
TYPE:
|
truncated |
Output was cut to fit the envelope.
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> TestRun
Build from the decoded run object.
Source code in src/ocx_sdk/_results.py
ToolBinding
dataclass
¶
One tool in a group of ocx status, and how far it is bound.
Binding state is key presence, not a status field: declared without
platforms is declared-but-unlocked, platforms without declared is a
stale lock entry nothing declares any more, and both means fully bound.
| ATTRIBUTE | DESCRIPTION |
|---|---|
declared |
The identifier
TYPE:
|
platforms |
Platform to digest, from the lock file, if it has an entry.
TYPE:
|
ref
property
¶
ref: PackageRef | None
The declared identifier as a PackageRef, or None if nothing declares it.
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> ToolBinding
Build from one decoded entry of a group's tools object.
ToolRow
dataclass
¶
One tool entry add, lock, update, or remove reports.
All four emit the same bare array — effectively "the lock entries that
changed", not a per-command envelope. remove reports an empty one.
| ATTRIBUTE | DESCRIPTION |
|---|---|
binding |
The binding name in
TYPE:
|
group |
The group it belongs to.
TYPE:
|
digest |
The digest for the current platform.
TYPE:
|
platforms |
Every platform's digest.
TYPE:
|
VerificationReport
dataclass
¶
VerificationReport(subject_digest: str, referrer_digest: str, certificate_identity: str, certificate_oidc_issuer: str, signed_at: str, signatures: tuple[SignatureEntry, ...] = ())
ocx package verify (C-012).
Payload is enveloped (D11): from_json unwraps data.
| ATTRIBUTE | DESCRIPTION |
|---|---|
subject_digest |
The manifest digest that was verified.
TYPE:
|
referrer_digest |
The verified object's own digest. Not always a
manifest digest — see
TYPE:
|
certificate_identity |
The keyless identity pinned for verification.
Plain
TYPE:
|
certificate_oidc_issuer |
The keyless OIDC issuer pinned for
verification. Always emitted (
TYPE:
|
signed_at |
When the signature was produced, as ocx spelled it.
Always emitted (
TYPE:
|
signatures |
Matching signatures found. Absent, not empty, when there were none (D7).
TYPE:
|
from_json
classmethod
¶
from_json(raw: str) -> VerificationReport
Parse ocx --format json package verify output.
Source code in src/ocx_sdk/_results.py
VersionInfo
dataclass
¶
VersionInfo(version: str, channel: str | None = None, cargo_pkg_version: str | None = None, commit: Mapping[str, Any] = _EMPTY, build: Mapping[str, Any] = _EMPTY, ci: Mapping[str, Any] = _EMPTY)
ocx version under --format json.
Only version is guaranteed; everything else depends on how the binary was
built. The three sub-objects stay mappings on purpose — they are build
provenance, nothing in the SDK dispatches on their fields, and modelling
them would pin a schema ocx explicitly keeps open for extension.
Note that Ocx.version() reads the plain output instead: a bare semver
line is ocx's documented stable contract (design §11).
from_json
classmethod
¶
from_json(raw: str) -> VersionInfo
Parse ocx --format json version output.
Source code in src/ocx_sdk/_results.py
WhichResult
dataclass
¶
Where one identifier resolves on disk, per package which.
| ATTRIBUTE | DESCRIPTION |
|---|---|
path |
The resolved location.
TYPE:
|
kind |
TYPE:
|
from_dict
classmethod
¶
from_dict(data: Mapping[str, Any]) -> WhichResult
Build from one decoded value of the keyed object.
BasicAuth
dataclass
¶
Username and password for a registry.
Example
BasicAuth("ci", "hunter2") BasicAuth(user='ci', password=*)
BearerAuth
dataclass
¶
A bearer token for a registry.
Example
BearerAuth("ghp_secret") BearerAuth(token=*)
Channel
¶
Bases: StrEnum
Release channel of the dist manifest.
HostEnv
dataclass
¶
A snapshot of the environment a spawned ocx inherits.
The mapping is copied and made read-only at construction, so neither a
later mutation of the source dict nor a write through .source can
rewrite a snapshot that was already taken. (A read-only snapshot is not
picklable — an implementation detail, not a contract.)
repr lists key names only. An ambient snapshot holds OCX_AUTH_*
values, and a repr is exactly what a traceback or a pytest diff prints.
Example
HostEnv({"PATH": "/usr/bin", "TOKEN": "s"}).without("TOKEN").source["PATH"] '/usr/bin'
clean
classmethod
¶
clean() -> HostEnv
Return an empty environment.
Hermetic, and a documented footgun: spawned tools lose PATH and fail
in ways that read like anything but a missing variable. minimal() is
the recovery.
Source code in src/ocx_sdk/_types.py
minimal
classmethod
¶
minimal(*, windows: bool | None = None) -> HostEnv
Return only the platform-essential variables from the ambient env.
PATH, HOME, and TMPDIR everywhere; SYSTEMROOT and TEMP on
Windows. Variables that are not set are simply absent.
| PARAMETER | DESCRIPTION |
|---|---|
windows
|
Force the platform branch. Defaults to detecting the host; tests pass it explicitly so both branches run anywhere.
TYPE:
|
Source code in src/ocx_sdk/_types.py
InstallEnv
¶
Bases: StrEnum
The OCX_INSTALL_* grammar the setup script defines.
bootstrap.ensure() honors these verbatim, one rung below its explicit
keyword arguments and one above its own defaults.
ListVar
dataclass
¶
An [env] value appended to a separated list.
| ATTRIBUTE | DESCRIPTION |
|---|---|
value |
The entry to append.
TYPE:
|
separator |
The list separator.
TYPE:
|
PackageRef
dataclass
¶
A package identifier carried verbatim from ocx, never parsed.
ocx owns the identifier grammar. The SDK stores the string it was given and hands it back unchanged, so a ref that came out of one result flows into the next call's argv byte-for-byte.
Identity is the identifier alone. metadata is decoration carried along
from whichever JSON row produced the ref, so two refs to the same package
from different commands must not compare unequal. The mapping is copied
and made read-only at construction (and is therefore not picklable).
Example
ref = PackageRef("ocx.sh/astral-sh/uv:0.9.7") str(ref) 'ocx.sh/astral-sh/uv:0.9.7'
PathVar
dataclass
¶
An [env] value prepended to a PATH-like variable, deduplicated.
RetryPolicy
dataclass
¶
RetryPolicy(attempts: int = 3, backoff: float = 1.0, multiplier: float = 2.0, max_backoff: float = 30.0, max_retry_after: float = 300.0, jitter: bool = True, retry_on: frozenset[ExitCode] = frozenset({TEMP_FAIL}), sleep: Callable[[float], None] | None = None)
How to retry a failure ocx classified as transient.
Attempt one is not a retry: attempts=3 means at most two backoff waits.
timeout is per attempt, so the worst case is
attempts * timeout + sum(backoff).
| ATTRIBUTE | DESCRIPTION |
|---|---|
attempts |
Total attempts, including the first.
TYPE:
|
backoff |
Delay before the first retry, in seconds.
TYPE:
|
multiplier |
Growth factor applied to
TYPE:
|
max_backoff |
Ceiling for the computed delay.
TYPE:
|
max_retry_after |
Ceiling for a server-supplied
TYPE:
|
jitter |
Draw the delay uniformly from
TYPE:
|
retry_on |
Exit codes worth retrying. Applies to the process path
only;
TYPE:
|
sleep |
Sleep seam, defaulting to
TYPE:
|
DistSource
dataclass
¶
DistSource(manifest_url: str | None = None, manifest_path: Path | None = None, manifest_data: bytes | None = None, sha256: str | None = None, auth: Auth | None = None, headers: Mapping[str, str] = _NO_HEADERS)
Where a dist manifest comes from, and how its body is trusted.
Build one with url(), path(), or data() rather than the constructor.
A source with no location at all is the canonical default: it resolves to
OCX_INSTALL_DIST_URL when the environment sets one, and to
DEFAULT_DIST_URL otherwise. A source built with an explicit URL never
consults the environment.
| ATTRIBUTE | DESCRIPTION |
|---|---|
manifest_url |
Explicit manifest URL, or
TYPE:
|
manifest_path |
Local manifest file.
TYPE:
|
manifest_data |
Manifest bytes the caller already holds.
TYPE:
|
sha256 |
Expected digest of the manifest body. Auto-derived from a
TYPE:
|
auth |
Credentials for the manifest host, bound to its origin.
TYPE:
|
headers |
Extra request headers, bound to the same origin.
TYPE:
|
Example
DistSource.url().manifest_url is None True
url
classmethod
¶
url(url: str | None = None, sha256: str | None = None, auth: Auth | None = None, headers: Mapping[str, str] | None = None) -> DistSource
Fetch the manifest over https.
| PARAMETER | DESCRIPTION |
|---|---|
url
|
Manifest URL.
TYPE:
|
sha256
|
Expected digest of the manifest body. Required whenever the
host is not
TYPE:
|
auth
|
Credentials for this origin, and this origin only.
TYPE:
|
headers
|
Extra request headers, bound to the same origin.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DistSource
|
The source. |
| RAISES | DESCRIPTION |
|---|---|
DistManifestError
|
|
Source code in src/ocx_sdk/_dist.py
path
classmethod
¶
path(path: Path | str, sha256: str | None = None) -> DistSource
Read the manifest from a local file.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
File holding the manifest JSON.
TYPE:
|
sha256
|
Expected digest of the file contents.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DistSource
|
The source. |
| RAISES | DESCRIPTION |
|---|---|
DistManifestError
|
|
Source code in src/ocx_sdk/_dist.py
data
classmethod
¶
data(raw: bytes, sha256: str | None = None) -> DistSource
Use manifest bytes the caller already has.
The vendoring path: ship a dist/<sha256>.json snapshot as package data
and read it back with importlib.resources, which works from a zipped
wheel where a filesystem path does not.
| PARAMETER | DESCRIPTION |
|---|---|
raw
|
The manifest body.
TYPE:
|
sha256
|
Expected digest of
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DistSource
|
The source. |
| RAISES | DESCRIPTION |
|---|---|
DistManifestError
|
|
Source code in src/ocx_sdk/_dist.py
resolve_url
¶
Return the URL this source fetches from.
| PARAMETER | DESCRIPTION |
|---|---|
env
|
Environment consulted for
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str | None
|
The manifest URL, or |
Source code in src/ocx_sdk/_dist.py
credentials
¶
Return this source's credentials, bound to its resolved origin.
| PARAMETER | DESCRIPTION |
|---|---|
env
|
Environment used to resolve the URL, as in
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Credentials
|
Credentials whose origin is the resolved URL's, or an unbound empty |
Credentials
|
set for a local or in-memory source. |
| RAISES | DESCRIPTION |
|---|---|
DistManifestError
|
The resolved URL is not usable — not https, or carrying userinfo. |
Source code in src/ocx_sdk/_dist.py
error_envelope
¶
error_envelope(error: OcxProcessError) -> ErrorEnvelope | None
Return the structured failure a non-zero exit carried, else None.
The dual of partial_report: where that recovers the report a
report-then-fail command wrote, this recovers the envelope a hard
failure wrote instead. A failure never carries both, so for any one
error at most one of the two answers.
try:
ocx.package.claim("acme/widget", repository="oci://ghcr.io/acme/widget")
except DataError as exc:
envelope = error_envelope(exc)
if envelope is None or "already claimed" not in envelope.message:
raise
| PARAMETER | DESCRIPTION |
|---|---|
error
|
The caught process failure.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ErrorEnvelope | None
|
|
ErrorEnvelope | None
|
an envelope. Otherwise the parsed envelope. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
stdout is an envelope missing one of its frozen keys — a binary outside the tested window, not a recoverable state. |
Source code in src/ocx_sdk/_results.py
partial_report
¶
partial_report(error: OcxProcessError) -> str | None
Return the report a non-zero-exit stdout carried, else None (D10).
Several ocx failures still print a full JSON report before exiting
non-zero: a --signature-format both sign or attest losing one leg, a
partially-failed tag sweep, a copy refused on a sidecar conflict, and a
push whose inline signing failed. OcxProcessError never parses its own
stdout, so a caller recovers the report explicitly:
try:
result = ocx.package.sign(ref, key="file://k.pem", rekor_upload=False)
except OcxProcessError as exc:
raw = partial_report(exc)
if raw is not None:
result = SignatureReport.from_json(raw)
else:
raise
| PARAMETER | DESCRIPTION |
|---|---|
error
|
The caught process failure.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str | None
|
|
str | None
|
and no |
str | None
|
there is nothing to recover. Otherwise |
str | None
|
for the matching |
Note
The enveloped shapes come back enveloped, not pre-unwrapped. D10's
text called for handing back the envelope's data sub-document, which
cannot work: SignatureReport/AttestationReport/SweepReport's own
from_json calls _envelope (D11), so a pre-unwrapped payload makes
it unwrap twice and raise on a missing data key — the example above
would not run. Returning stdout whole is what makes one from_json
serve the success path and the recovery path, which is the property
D10 and S-009 both ask for; the discriminator is unchanged.
Source code in src/ocx_sdk/_results.py
tolerated_report
¶
tolerated_report(result: CommandResult) -> str
Return the report a report-then-fail command wrote, or raise its failure.
package test, cascade check and cascade repair exit non-zero with
their report on stdout when the outcome is a finding rather than a fault —
the client tolerates that code (ok_codes) so the report comes back as a
result. The same code with an error envelope, or with no JSON at all, is a
fault the tolerance must not swallow: this raises it as the exception the
exit code maps to, stdout preserved for error_envelope(err).
| PARAMETER | DESCRIPTION |
|---|---|
result
|
The finished call, exit code and both streams.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
|
| RAISES | DESCRIPTION |
|---|---|
OcxProcessError
|
The exit was non-zero and stdout carried no report —
the subclass |
Source code in src/ocx_sdk/_results.py
ensure
¶
ensure(version: str | None = None, *, channel: Channel = STABLE, dist: DistSource | None = None, mirror_url: str | None = None, ca_bundle: str | None = None, min_version: str | None = None, cache_dir: Path | None = None, env: HostEnv | None = None, trust_cache: bool = False, retry: RetryPolicy | None = None, timeout: float | None = None) -> Path
Provision a verified ocx binary and return its path.
Idempotent and offline-friendly: a cache hit that still hashes correctly
needs no network at all. Every knob resolves explicit argument first, then
the matching OCX_INSTALL_* variable from env, then the default.
| PARAMETER | DESCRIPTION |
|---|---|
version
|
Exact version to install.
TYPE:
|
channel
|
Channel consulted when
TYPE:
|
dist
|
Where the manifest comes from.
TYPE:
|
mirror_url
|
Base URL that replaces the artifact host, as
TYPE:
|
ca_bundle
|
PEM file trusted for every download, replacing the system
trust store, falling back to
TYPE:
|
min_version
|
Operator floor. A resolved version below it fails loudly instead of installing something older than the caller allows.
TYPE:
|
cache_dir
|
Cache root.
TYPE:
|
env
|
Environment snapshot.
TYPE:
|
trust_cache
|
Skip the digest re-check on a cache hit. Orthogonal to
TYPE:
|
retry
|
Policy for transient transport failures;
TYPE:
|
timeout
|
Per-attempt network budget in seconds.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Path
|
Path to the installed binary, mode |
| RAISES | DESCRIPTION |
|---|---|
BootstrapError
|
The cache root is untrusted, or the resolved version is
below |
DistManifestError
|
The manifest is unusable, or its archive is. |
UnsupportedPlatformError
|
No release matches this platform. |
ChecksumMismatchError
|
Downloaded bytes do not match the manifest. Never retried — the bytes are wrong, not late. |
DownloadError
|
The manifest or artifact could not be fetched, or the CA bundle could not be loaded. |
Source code in src/ocx_sdk/_bootstrap.py
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | |