Extension release catalog
client.extension_catalog reads Core's retained release catalog and exposes
its explicit administrator commands. It applies to app, service and tool
metadata. It does not deploy workloads or replace client.extensions.
catalog = client.extension_catalog.get_catalog()
print(catalog.core_version, catalog.digest_pins_required)
for item in catalog.extensions:
print(item.name, item.selected, item.latest_compatible)
digest_pins_required is None on older servers that do not report the policy;
do not treat absence as False. Release IDs are opaque strings, not UUIDs.
Response fields, statuses and provenance values remain open to new server data.
Import a release payload reviewed from its publisher:
from kamiwaza_sdk.schemas.extension_catalog import ImportCatalogReleases
catalog = client.extension_catalog.import_releases(
ImportCatalogReleases(
releases=[reviewed_release],
template_types={reviewed_release["name"]: "app"},
source="reviewed-publisher-bundle",
)
)
Import retains immutable release metadata; it neither selects that release nor
creates a deployment. Metadata is durable: do not put secret values in imported
Compose content. Pin enforcement may reject a new unpinned release. Canonical
release validation always applies, and the shipped baseline has its separate
integrity contract. Withdrawing an existing release uses the same immutable
payload with withdrawn=True; it retains history and does not stop running
workloads. A changed payload under the same release identity remains a conflict.
An administrator can select a reviewed release for future deployments:
from kamiwaza_sdk.schemas.extension_catalog import SelectCatalogRelease
entry = next(item for item in catalog.extensions if item.name == release_name)
catalog = client.extension_catalog.select_release(
SelectCatalogRelease(
name=entry.name,
release_id=reviewed_release_id,
expected_revision=entry.selection_revision,
)
)
Core checks the current revision and compatibility. A product-line conflict
includes the confirmation value; pass it only after reviewing the proposed
product switch. For a removable, non-baseline extension, an explicit
release_id=None removes its selection. The SDK preserves that null value.
Removing a selection retains release and template history.
preview_updates() reads an administrator-only proposal. apply_updates()
requires an explicit ApplyCatalogUpdates request with the reviewed changes
and original preview_hash. It does not fetch or approve a new preview for the
caller, recalculate the hash, retry conflicts, or upgrade running workloads.
refresh() may contact Core's configured remote catalog. It updates discovered
availability but does not select a release; inspect source_status,
refresh_summary and unpublished_sources for partial or failed discovery.
Agent tools require approval for every mutation, including refresh and import.
Live publication-policy replay
tests/integration/test_extension_catalog_live.py is selected by
pytest -m integration. The two explicit phases use a fresh, private
KAMIWAZA_TEST_CATALOG_JOURNAL path and require trusted platform HTTPS plus
KAMIWAZA_TEST_DISPOSABLE_IDENTITIES=1.
With server pin enforcement disabled, set
KAMIWAZA_TEST_CATALOG_PHASE=seed and run
test_catalog_accepts_owned_unpinned_release_with_policy_disabled. Normally
this test retires its release before returning. A coordinating operator may
set KAMIWAZA_TEST_CATALOG_HANDOFF=1 to retain that one owned release for the
next phase; the operator then owns cleanup even if the second phase never runs.
After enabling the server's pin policy, set the phase to enforced and run
test_catalog_enforces_pins_and_retires_retained_release_metadata with the same
journal. It proves that the old unpinned release remains reimportable and can
be withdrawn, a new unpinned release is refused, a pinned release is accepted,
immutable modification is refused, an ordinary reader cannot import, and
existing catalog metadata remains unchanged. All synthetic releases use
example.invalid images; nothing is pulled or deployed.
The journal restricts cleanup to its random prefix, endpoint and exact synthetic payloads. Cleanup withdraws eligible owned releases and independently rereads the catalog. Retained history is not deleted. The operator must restore the original server configuration and independently inspect the final state. Neither phase certifies canonical/baseline exemptions or unrecognized-value logging; the emitted capability records retain those gaps and identify the opposite policy phase separately.
Release compatibility in the live policy replay
Older catalog responses can omit the optional digest_pins_required field
(the SDK represents this as None). The live two-phase catalog tests accept
missing observation metadata, but still reject a reported value that contradicts
the phase. They establish enforcement through actual import behavior: accept an
owned unpinned release while disabled; while enabled refuse a new unpinned
release, accept a digest-pinned one, reject an immutable-payload change, and
withdraw/reimport the retained legacy release without reactivating it. Ordinary
reader/admin boundaries, unrelated-catalog equality and owned-row retirement
remain asserted. Missing metadata is never interpreted as False or True.
The operator must own the test environment, journal both policy settings and restore the original configuration. These checks publish metadata only, pull no images and deploy no workload. Canonical/baseline exemptions and invalid-flag logging remain outside this replay; existing evidence-map residuals are preserved.
For a separately registered bounded publication-metadata journey, the explicit
tests/e2e/catalog_policy_publication_map.yaml maps only the enforced-phase node.
The disabled seed phase is preparation, not release credit. The supplied
verification scope must exclude canonical validation, baseline exemptions,
invalid-flag reporting, image pulls and workload deployment. The normal broad
map remains unchanged and retains its required unverified groups. Do not use the
scoped record as an unrestricted capability verdict.
Prepare owned metadata with the policy disabled, enable it on the isolated target, then capture the stable enabled configuration before and after the enforced node. Its finally block retires all owned metadata and checks unrelated rows unchanged. Restore the original operator configuration after this captured replay and verify health plus exact restoration before publishing the packet. Retained withdrawn catalog history is not physical deletion.