From 69eba9f0e7e60907334a0514f19c84bb48a22f4c Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Thu, 5 Nov 2026 07:06:47 +0800 Subject: [PATCH] Add bounded authorized Volume usage reads for Engine 369 --- .github/workflows/security-release-gate.yml | 14 + COMPATIBILITY.md | 13 + README.md | 6 + code/framework/api-pub-sub-jetty/pom.xml | 2 +- code/framework/api-pub-sub/pom.xml | 2 +- code/framework/api/pom.xml | 2 +- code/framework/archaius/pom.xml | 2 +- code/framework/async/pom.xml | 2 +- code/framework/auditing/pom.xml | 2 +- code/framework/db-loader/pom.xml | 2 +- code/framework/deferred/pom.xml | 2 +- code/framework/encryption/pom.xml | 2 +- code/framework/engine/pom.xml | 2 +- code/framework/eventing/pom.xml | 2 +- code/framework/events/pom.xml | 2 +- code/framework/extension-spring/pom.xml | 2 +- code/framework/extension/pom.xml | 2 +- code/framework/java-server/pom.xml | 2 +- code/framework/jmx/pom.xml | 2 +- code/framework/jooq/pom.xml | 2 +- code/framework/json/pom.xml | 2 +- code/framework/launcher/pom.xml | 2 +- code/framework/lock/pom.xml | 2 +- code/framework/logback/pom.xml | 2 +- code/framework/managed-context/pom.xml | 2 +- code/framework/metrics/pom.xml | 2 +- code/framework/module/pom.xml | 2 +- code/framework/object/pom.xml | 2 +- code/framework/pool/pom.xml | 2 +- code/framework/resource-monitor/pom.xml | 2 +- code/framework/schema/pom.xml | 2 +- code/framework/server/pom.xml | 2 +- code/framework/spring/pom.xml | 2 +- code/framework/system-task/pom.xml | 2 +- code/framework/token/pom.xml | 2 +- code/framework/utils/pom.xml | 2 +- code/iaas/agent-instance/pom.xml | 2 +- code/iaas/agent-server/pom.xml | 2 +- code/iaas/agent/pom.xml | 2 +- code/iaas/allocator/pom.xml | 2 +- code/iaas/api-logic/pom.xml | 2 +- code/iaas/archaius-management/pom.xml | 2 +- code/iaas/auth-logic/pom.xml | 2 +- .../auth/ai/view/AiResourceViewService.java | 148 +- .../core/dao/impl/VolumeUsageDaoTest.java | 55 + .../auth/ai/view/AiVolumeUsageViewTest.java | 266 +++ code/iaas/bootstrap/pom.xml | 2 +- code/iaas/config-item/api/pom.xml | 2 +- code/iaas/config-item/common/pom.xml | 2 +- code/iaas/config-item/server/pom.xml | 2 +- code/iaas/engine-jooq/pom.xml | 2 +- code/iaas/events/pom.xml | 2 +- code/iaas/external-handler/pom.xml | 2 +- code/iaas/ha/pom.xml | 2 +- code/iaas/healthcheck/pom.xml | 2 +- code/iaas/labels/pom.xml | 2 +- code/iaas/logic-common/pom.xml | 2 +- code/iaas/logic/pom.xml | 2 +- code/iaas/metadata/pom.xml | 2 +- code/iaas/model/pom.xml | 2 +- .../cattle/platform/core/dao/VolumeDao.java | 3 + .../platform/core/dao/impl/VolumeDaoImpl.java | 17 + code/iaas/resource-pool/pom.xml | 2 +- code/iaas/service-discovery/api/pom.xml | 2 +- code/iaas/service-discovery/server/pom.xml | 2 +- code/iaas/ssh-common/pom.xml | 2 +- code/iaas/storage-service/pom.xml | 2 +- code/iaas/task-jooq/pom.xml | 2 +- code/implementation/activity-log/pom.xml | 2 +- .../agent-instance-impl/pom.xml | 2 +- code/implementation/docker/api/pom.xml | 2 +- code/implementation/docker/common/pom.xml | 2 +- code/implementation/docker/compute/pom.xml | 2 +- code/implementation/docker/machine/pom.xml | 2 +- code/implementation/docker/storage/pom.xml | 6 +- code/implementation/extension-api/pom.xml | 2 +- code/implementation/hazelcast/common/pom.xml | 2 +- .../implementation/hazelcast/eventing/pom.xml | 2 +- code/implementation/hazelcast/lock/pom.xml | 2 +- code/implementation/host-api/pom.xml | 2 +- code/implementation/host-stats/pom.xml | 2 +- code/implementation/register/pom.xml | 2 +- code/implementation/sample-setup/pom.xml | 2 +- code/implementation/settings-api/pom.xml | 2 +- .../simulator/agent-connection/pom.xml | 2 +- code/implementation/simulator/storage/pom.xml | 2 +- code/implementation/system-stack/pom.xml | 2 +- code/implementation/vm/pom.xml | 2 +- code/meta-parent/pom.xml | 2 +- code/packaging/app-config/pom.xml | 2 +- code/packaging/app/pom.xml | 2 +- code/packaging/bundle/pom.xml | 2 +- code/packaging/dev/pom.xml | 2 +- code/packaging/meta/pom.xml | 2 +- code/parent/pom.xml | 2 +- .../orchestration-engine-0.183.369.md | 23 + pom.xml | 2 +- resources/pom.xml | 2 +- scripts/api-key-operation-contract.json | 2128 +++++++++-------- scripts/api-key-operation-inventory.json | 488 ++-- .../api-key-operation-review-0.183.369.json | 57 + scripts/build | 2 +- scripts/check-cattle-jdk25-standalone | 2 +- scripts/check-pasturestack-source | 4 +- scripts/check-release-artifact | 2 +- 105 files changed, 2084 insertions(+), 1326 deletions(-) create mode 100644 code/iaas/auth-logic/src/test/java/io/cattle/platform/core/dao/impl/VolumeUsageDaoTest.java create mode 100644 code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/view/AiVolumeUsageViewTest.java create mode 100644 docs/releases/orchestration-engine-0.183.369.md create mode 100644 scripts/api-key-operation-review-0.183.369.json diff --git a/.github/workflows/security-release-gate.yml b/.github/workflows/security-release-gate.yml index d7431042f9..3595f61a4d 100644 --- a/.github/workflows/security-release-gate.yml +++ b/.github/workflows/security-release-gate.yml @@ -252,6 +252,20 @@ jobs: 'approvedTcpSurvivesJsonReloadHumanReviewNativeDispatchAndOneReceipt', 'changedApprovedTcpBodyAndCurrentRoleCannotReachTheDurableClaim', }, + 'io.cattle.platform.iaas.api.auth.ai.view.AiVolumeUsageViewTest': { + 'activeAndStoppedSameNameReferencesUseFreshOwnersAndAuthorizedStackNames', + 'hiddenForeignRemovedOrUnreadableParentsNeverExposeIdentitiesOrCounts', + 'boundedSnapshotAndEmptyOrLegacyMetadataNeverClaimUnusedOrComplete', + 'realCustomKeyOwnerAuditsAllowAndDenyWithReadOnlyDispatchAndNoExtraGrant', + 'unattestedCustomKeyManagerReturnsUnknownWithoutTargetInspectionOrFallback', + 'laterTargetKeyRevisionRevocationAbortsTheWholeReadAndRestoresContext', + 'nativeCoreProjectionRetainsSchemaFieldVisibilityAndNeverInvokesDtoAugmentation', + 'volumeScalarsMatchOriginalNativeWrappingForJwtFullAndLegacyIncludingSchemaAliasesAndTransforms', + }, + 'io.cattle.platform.core.dao.impl.VolumeUsageDaoTest': { + 'nativeSqlBoundsRelationshipCandidatesBeforeMaterializationIncludingStoppedContainers', + 'nativeSqlExcludesEveryForeignRemovedAndNonContainerRelationshipWithoutWrites', + }, } suites = [] observed = {} diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index 4b99352203..f3c912e35f 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -1,5 +1,18 @@ # Compatibility Contract +## Engine 0.183.369 candidate — not published + +The existing typed Volume detail gains at most 50 freshly authorized container +references from a native SQL snapshot bounded to 51 rows. Completeness remains +unknown; missing results cannot establish unused or safe-to-delete status. +Current role-schema scalar values, Key scopes and canonical read audit remain; +no output-filter, operation grant or deletion-oracle change is introduced. +Native parent names require a readable persisted Stack relation and fresh read. +Matching Web Console 1.6.208 / bridge 0.2.10, original artifact qualification +and native workflow acceptance remain pending. Required test identities are +132 preserved plus ten new methods (142); see the +[candidate note](docs/releases/orchestration-engine-0.183.369.md). + ## Engine 0.183.368 release This release adds an optional TCP `healthCheck` to the existing typed External diff --git a/README.md b/README.md index 83add06307..b26be0f433 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,12 @@ Rancher 1.6 ecosystem. It is not affiliated with Rancher Labs or SUSE. This fork of [`rancher/cattle`](https://github.com/rancher/cattle) preserves upstream history, authorship, licenses, and dependency notices. +## Next candidate: Engine 0.183.369 + +[Volume usage safe reads](docs/releases/orchestration-engine-0.183.369.md) are under +source/CI preparation with matching Web Console 1.6.208 / bridge 0.2.10. This +candidate is not published or runtime-qualified. + ## Latest published release: Engine 0.183.368 [Engine 0.183.368](https://github.com/PastureStack/orchestration-engine/releases/tag/v0.183.368) diff --git a/code/framework/api-pub-sub-jetty/pom.xml b/code/framework/api-pub-sub-jetty/pom.xml index 13a060b2e0..ef32e38c60 100644 --- a/code/framework/api-pub-sub-jetty/pom.xml +++ b/code/framework/api-pub-sub-jetty/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/api-pub-sub/pom.xml b/code/framework/api-pub-sub/pom.xml index a35124cb9c..882100e841 100644 --- a/code/framework/api-pub-sub/pom.xml +++ b/code/framework/api-pub-sub/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/api/pom.xml b/code/framework/api/pom.xml index 16fbfe25fd..42bb78aff3 100644 --- a/code/framework/api/pom.xml +++ b/code/framework/api/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/archaius/pom.xml b/code/framework/archaius/pom.xml index a18d27308d..6292c7f365 100644 --- a/code/framework/archaius/pom.xml +++ b/code/framework/archaius/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-meta-parent - 0.183.368 + 0.183.369 ../../meta-parent/pom.xml diff --git a/code/framework/async/pom.xml b/code/framework/async/pom.xml index cb9cf23eb5..6154f76eb3 100644 --- a/code/framework/async/pom.xml +++ b/code/framework/async/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/auditing/pom.xml b/code/framework/auditing/pom.xml index 69745871e6..a35a6c3406 100644 --- a/code/framework/auditing/pom.xml +++ b/code/framework/auditing/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/db-loader/pom.xml b/code/framework/db-loader/pom.xml index ee36d81379..418945bb62 100644 --- a/code/framework/db-loader/pom.xml +++ b/code/framework/db-loader/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/deferred/pom.xml b/code/framework/deferred/pom.xml index 6530d804b0..f431676b79 100644 --- a/code/framework/deferred/pom.xml +++ b/code/framework/deferred/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/encryption/pom.xml b/code/framework/encryption/pom.xml index 84c15a83e6..1083826ad1 100644 --- a/code/framework/encryption/pom.xml +++ b/code/framework/encryption/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/engine/pom.xml b/code/framework/engine/pom.xml index ca2a6c4329..cd716e1534 100644 --- a/code/framework/engine/pom.xml +++ b/code/framework/engine/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/eventing/pom.xml b/code/framework/eventing/pom.xml index 803d3d79af..0ebbcf801c 100644 --- a/code/framework/eventing/pom.xml +++ b/code/framework/eventing/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/events/pom.xml b/code/framework/events/pom.xml index 5bd358613a..740483596a 100644 --- a/code/framework/events/pom.xml +++ b/code/framework/events/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/extension-spring/pom.xml b/code/framework/extension-spring/pom.xml index 94cabfa9d4..fc390c500a 100644 --- a/code/framework/extension-spring/pom.xml +++ b/code/framework/extension-spring/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/extension/pom.xml b/code/framework/extension/pom.xml index 1b3414caea..af2460c68e 100644 --- a/code/framework/extension/pom.xml +++ b/code/framework/extension/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/java-server/pom.xml b/code/framework/java-server/pom.xml index 0e92141852..34fdb69cbf 100644 --- a/code/framework/java-server/pom.xml +++ b/code/framework/java-server/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/jmx/pom.xml b/code/framework/jmx/pom.xml index ffd93c1c77..1845ba2261 100644 --- a/code/framework/jmx/pom.xml +++ b/code/framework/jmx/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/jooq/pom.xml b/code/framework/jooq/pom.xml index db0620f57c..eb18fb5776 100644 --- a/code/framework/jooq/pom.xml +++ b/code/framework/jooq/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/json/pom.xml b/code/framework/json/pom.xml index 20fdaabd37..0ceb07876b 100644 --- a/code/framework/json/pom.xml +++ b/code/framework/json/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/launcher/pom.xml b/code/framework/launcher/pom.xml index e4de6fcce0..55dc54b965 100644 --- a/code/framework/launcher/pom.xml +++ b/code/framework/launcher/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/lock/pom.xml b/code/framework/lock/pom.xml index 42bb731c62..db0e5f3ab7 100644 --- a/code/framework/lock/pom.xml +++ b/code/framework/lock/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/logback/pom.xml b/code/framework/logback/pom.xml index 650b6b07bb..7b43645b15 100644 --- a/code/framework/logback/pom.xml +++ b/code/framework/logback/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-meta-parent - 0.183.368 + 0.183.369 ../../meta-parent/pom.xml diff --git a/code/framework/managed-context/pom.xml b/code/framework/managed-context/pom.xml index d7a48ea2eb..0d71500f99 100644 --- a/code/framework/managed-context/pom.xml +++ b/code/framework/managed-context/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/metrics/pom.xml b/code/framework/metrics/pom.xml index e3a613850d..e12bccccb7 100644 --- a/code/framework/metrics/pom.xml +++ b/code/framework/metrics/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/module/pom.xml b/code/framework/module/pom.xml index ae0ae3eae1..fad83c50d0 100644 --- a/code/framework/module/pom.xml +++ b/code/framework/module/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/object/pom.xml b/code/framework/object/pom.xml index 5e9986d619..fe56c00d63 100644 --- a/code/framework/object/pom.xml +++ b/code/framework/object/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/pool/pom.xml b/code/framework/pool/pom.xml index 089e0d4b4e..4f444e77c1 100644 --- a/code/framework/pool/pom.xml +++ b/code/framework/pool/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/resource-monitor/pom.xml b/code/framework/resource-monitor/pom.xml index febd2ec750..15cd336924 100644 --- a/code/framework/resource-monitor/pom.xml +++ b/code/framework/resource-monitor/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/schema/pom.xml b/code/framework/schema/pom.xml index 2f431c8895..94044d2a1d 100644 --- a/code/framework/schema/pom.xml +++ b/code/framework/schema/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/server/pom.xml b/code/framework/server/pom.xml index 1a9d6ac54b..bf9b5a1de8 100644 --- a/code/framework/server/pom.xml +++ b/code/framework/server/pom.xml @@ -4,7 +4,7 @@ cattle-meta-parent io.cattle - 0.183.368 + 0.183.369 ../../meta-parent/pom.xml diff --git a/code/framework/spring/pom.xml b/code/framework/spring/pom.xml index 24bdf5290b..a55aac8a8e 100644 --- a/code/framework/spring/pom.xml +++ b/code/framework/spring/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/system-task/pom.xml b/code/framework/system-task/pom.xml index 39e6c473d7..478a735931 100644 --- a/code/framework/system-task/pom.xml +++ b/code/framework/system-task/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/token/pom.xml b/code/framework/token/pom.xml index ca4a99a212..18df61d5e3 100644 --- a/code/framework/token/pom.xml +++ b/code/framework/token/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/framework/utils/pom.xml b/code/framework/utils/pom.xml index 417a6041d3..58ea1e8635 100644 --- a/code/framework/utils/pom.xml +++ b/code/framework/utils/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/agent-instance/pom.xml b/code/iaas/agent-instance/pom.xml index aa0bc4b070..e2bc11401b 100644 --- a/code/iaas/agent-instance/pom.xml +++ b/code/iaas/agent-instance/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/agent-server/pom.xml b/code/iaas/agent-server/pom.xml index 42b97d8ea0..bc333c81ab 100644 --- a/code/iaas/agent-server/pom.xml +++ b/code/iaas/agent-server/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/agent/pom.xml b/code/iaas/agent/pom.xml index e7b69b3364..d68113ba2e 100644 --- a/code/iaas/agent/pom.xml +++ b/code/iaas/agent/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/allocator/pom.xml b/code/iaas/allocator/pom.xml index 5daa77764d..e3e32d0e57 100644 --- a/code/iaas/allocator/pom.xml +++ b/code/iaas/allocator/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/api-logic/pom.xml b/code/iaas/api-logic/pom.xml index c42bd09caf..9b7c54189c 100644 --- a/code/iaas/api-logic/pom.xml +++ b/code/iaas/api-logic/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/archaius-management/pom.xml b/code/iaas/archaius-management/pom.xml index c7528fad76..996d640041 100644 --- a/code/iaas/archaius-management/pom.xml +++ b/code/iaas/archaius-management/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/auth-logic/pom.xml b/code/iaas/auth-logic/pom.xml index 83f46870b4..189d0951ef 100644 --- a/code/iaas/auth-logic/pom.xml +++ b/code/iaas/auth-logic/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiResourceViewService.java b/code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiResourceViewService.java index efaf6d6939..2d3f85be53 100644 --- a/code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiResourceViewService.java +++ b/code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiResourceViewService.java @@ -7,7 +7,15 @@ import io.cattle.platform.iaas.api.auth.apikey.ApiKeyCredentialContext; import io.cattle.platform.iaas.api.auth.apikey.ApiKeyAiBridgeGuard; import io.cattle.platform.core.model.Account; +import io.cattle.platform.core.dao.VolumeDao; +import io.cattle.platform.core.model.Mount; +import io.cattle.platform.core.model.Volume; +import io.cattle.platform.core.model.Instance; +import io.cattle.platform.core.model.Stack; +import io.github.ibuildthecloud.gdapi.model.impl.SchemaImpl; +import io.github.ibuildthecloud.gdapi.model.impl.WrappedResource; import io.cattle.platform.object.ObjectManager; +import io.cattle.platform.object.util.DataUtils; import io.cattle.platform.iaas.api.auth.impl.ApiAuthenticator; import io.cattle.platform.util.type.CollectionUtils; import io.github.ibuildthecloud.gdapi.condition.Condition; @@ -82,6 +90,7 @@ public class AiResourceViewService { @Inject ResourceManagerLocator managers; @Inject ObjectManager objects; @Inject io.cattle.platform.iaas.api.auth.change.AiResourceChangeDomain resourceChanges; + @Inject VolumeDao volumes; public Map read(ApiRequest request) { Map input = input(request); @@ -172,11 +181,18 @@ protected Map fetch(ApiRequest domain, Map input } List> visible = new ArrayList<>(); for (Object row : rows) { - Resource resource = manager.convertResponse(row, domain); + Resource resource = "volume".equals(type) && domain.getId() != null + ? coreDetail(row, domain) : manager.convertResponse(row, domain); if (resource == null) throw error(503, "ResourceViewUnavailable"); String id = "processPool".equals(type) ? poolId(resource.getFields()) : resource.getId(); if (id == null) throw error(503, "ResourceViewUnavailable"); Map safe = project(type, id, resource.getFields()); + if ("volume".equals(type) && domain.getId() != null) { + for (String field : List.of("isHostPath", "isNative", "sizeMb")) scalar(safe, resource.getFields(), field); + if (resource.getFields().get("created") instanceof java.util.Date created) safe.put("created", created); + if (resource.getFields().containsKey("removed")) safe.put("removed", resource.getFields().get("removed")); + volumeUsage(domain, id, safe); + } if ("dnsService".equals(type)) safe.putAll(resourceChanges.aliasViewTargets(domain, id, domain.getId() != null)); if ("processPool".equals(type) && (!(safe.get("name") instanceof String name) || name.isBlank())) safe.put("name", "Process pool " + id.substring(5, 17)); @@ -259,6 +275,136 @@ private void enrichParents(ApiRequest domain, List> page) { } } + private void volumeUsage(ApiRequest domain, String id, Map safe) { + // Never infer unused, a hidden count or completeness from this bounded, + // permission-filtered snapshot. The native deletion oracle is separate. + safe.put("usageReferencesStatus", "unknown"); + List> references = new ArrayList<>(); + safe.put("usageReferences", references); + if (volumes == null) return; + long volumeId; + try { volumeId = Long.parseLong(rawId(id).toString()); } + catch (NumberFormatException invalid) { throw error(503, "ResourceViewUnavailable"); } + if (volumeId <= 0 || !sameId(domain.getId(), id)) throw error(503, "ResourceViewUnavailable"); + List mounts = volumes.getUsageMounts(ApiUtils.getPolicy().getAccountId(), volumeId); + if (mounts == null || mounts.size() > 51) throw error(503, "ResourceViewUnavailable"); + for (Mount mount : mounts.subList(0, Math.min(50, mounts.size()))) { + if (mount == null || !Long.valueOf(volumeId).equals(mount.getVolumeId()) + || mount.getInstanceId() == null || mount.getRemoved() != null) continue; + Resource target = usageTarget(domain, "container", mount.getInstanceId().toString()); + if (target == null || !"container".equals(target.getType()) || !(target.getFields().get("name") instanceof String) + || !(target.getFields().get("state") instanceof String)) continue; + String path = mount.getPath(); + if (path == null || !path.startsWith("/") || path.length() > 1024 + || path.chars().anyMatch(value -> value < 32 || value == 127) + || !("ro".equals(mount.getPermissions()) || "rw".equals(mount.getPermissions()))) continue; + Map reference = new LinkedHashMap<>(); + reference.put("containerId", target.getId()); + scalar(reference, target.getFields(), "name"); scalar(reference, target.getFields(), "state"); + reference.put("mountPath", path); reference.put("readOnly", "ro".equals(mount.getPermissions())); + reference.put("stackResolution", "unknown"); + // The native container owns its persisted Stack reference. Never + // infer names from labels or a cross-scope relationship SQL join. + Object stackId = target.getFields().get("stackId"); + if (stackId instanceof String || stackId instanceof Number) { + Resource stack = usageTarget(domain, "stack", stackId.toString()); + if (stack != null && stack.getFields().get("name") instanceof String name && !name.isBlank() && name.length() <= 512) { + reference.put("stackName", name); reference.put("stackResolution", "resolved"); + } + } + references.add(reference); + } + } + + private Resource usageTarget(ApiRequest domain, String type, String id) { + ApiRequest child = new ApiRequest(domain); + child.setRequestServletContext(domain.getServletContext()); + child.setType(type); child.setId(rawId(id).toString()); child.setMethod("GET"); + child.setAction(null); child.setLink(null); child.setRequestObject(null); + child.setRequestParams(new LinkedHashMap<>()); child.setConditions(new LinkedHashMap<>()); child.setInclude(null); + child.setAttribute(DOMAIN_READ_ATTRIBUTE, Boolean.TRUE); + ApiKeyCredentialContext key = ApiKeyCredentialContext.get(domain); + if (key != null) ApiKeyCredentialContext.attach(child, key); + Policy owner = keyAuthorization.actor(child); + ApiContext context = ApiContext.getContext(); + ApiRequest previous = context.getApiRequest(); Object previousPolicy = context.getPolicy(); + try { + var authority = authenticator.currentAuthorization(owner.getAuthenticatedAsAccountId(), owner.getAccountId(), child); + child.setSchemaFactory(authority.schemas()); + context.setApiRequest(child); context.setPolicy(authority.policy()); + Schema schema = authority.schemas().getSchema(type); + if (schema == null || schema.getResourceMethods() == null || !schema.getResourceMethods().contains("GET")) return null; + ResourceManager manager = managers.getResourceManagerByType(type); + if (manager == null) return null; + // A relationship candidate is not a caller-supplied API target. + // The attested native getById query applies this exact Key guard + // before materialization; do not synthesize per-hidden-target audit + // events whose IDs or event count would disclose the relation. + if (key != null && key.restricted() && !manager.supportsScopedCollectionQuery(keyAccess)) return null; + Object row = manager.getById(type, child.getId(), new ListOptions(child)); + if (row == null) return null; + Resource resource = coreDetail(row, child); + if (resource == null || resource.getId() == null || !sameId(resource.getId(), id) + || resource.getFields().get("removed") != null) return null; + return resource; + } catch (ClientVisibleException denied) { + if (!Set.of("KeyScopeDenied", "KeyPolicyDenied", "OwnerPermissionDenied", "NotFound").contains(denied.getCode())) throw denied; + return null; + } finally { + context.setApiRequest(previous); context.setPolicy(previousPolicy); + } + } + + /** Called only after native getById (including object authorization) and the fresh Key decision. */ + private Resource coreDetail(Object row, ApiRequest request) { + Long id, account; java.util.Date removed; + if ("volume".equals(request.getType()) && row instanceof Volume volume) { + id = volume.getId(); account = volume.getAccountId(); removed = volume.getRemoved(); + } else if ("container".equals(request.getType()) && row instanceof Instance instance && "container".equals(instance.getKind())) { + id = instance.getId(); account = instance.getAccountId(); removed = instance.getRemoved(); + } else if ("stack".equals(request.getType()) && row instanceof Stack stack) { + id = stack.getId(); account = stack.getAccountId(); removed = stack.getRemoved(); + } else throw error(503, "ResourceViewUnavailable"); + if (id == null || !sameId(id, request.getId()) || account == null + || account != ApiUtils.getPolicy().getAccountId() || removed != null) throw error(404, "NotFound"); + Schema schema = request.getSchemaFactory().getSchema(request.getType()); + if (schema == null || schema.getResourceFields() == null || !schema.getResourceFields().containsKey("id")) + throw error(403, "OwnerPermissionDenied"); + List names = "volume".equals(request.getType()) + ? List.of("name", "description", "state", "kind", "created", "removed", "driver", "accessMode", "size", "sizeMb", "isHostPath", "isNative") + : "container".equals(request.getType()) ? List.of("name", "state", "stackId") : List.of("name"); + // Reuse the exact role-schema Field accessors and native wrapping rules + // (including aliases and reference formatting), + // with a bounded field subset. No full DTO/output augmentation runs. + SchemaImpl projection = new SchemaImpl(); projection.setId(schema.getId()); projection.setParent(schema.getParent()); + Map fields = new LinkedHashMap<>(); + fields.put("id", schema.getResourceFields().get("id")); + for (String name : names) { + var field = schema.getResourceFields().get(name); + // Sensitive/create-only accessors must not run, even transiently. + if (field != null && field.isIncludeInList() && !field.isReadOnCreateOnly() + && (field.getTransform() == null || field.getTransform().isBlank())) fields.put(name, field); + } + projection.setResourceFields(fields); + // Native wrapping gives persisted data fields precedence over bean getters. + // Copy only the already-approved scalar subset, never attachments or transformed values. + Map nativeFields = DataUtils.getFields(row), additional = new LinkedHashMap<>(); + for (String name : fields.keySet()) { + Object value = nativeFields.get(name); + if (value instanceof String || value instanceof Number || value instanceof Boolean || value instanceof java.util.Date) + additional.put(name, value); + } + Resource wrapped = new WrappedResource(ApiContext.getContext().getIdFormatter(), request.getSchemaFactory(), projection, + row, additional, Set.of(), "GET", false); + if (row instanceof Instance instance && (!sameId(wrapped.getFields().get("stackId"), instance.getStackId()))) + wrapped.getFields().remove("stackId"); + return wrapped; + } + + private static boolean sameId(Object left, Object right) { + return left != null && right != null && rawId(left.toString()).toString().equals(rawId(right.toString()).toString()); + } + /** No recursive copy: nested credentials, values, payloads and launchConfig stay inside the server. */ public static Map project(String type, String id, Map fields) { if (!READ_TYPES.contains(type) || id == null || fields == null) throw error(503, "ResourceViewUnavailable"); diff --git a/code/iaas/auth-logic/src/test/java/io/cattle/platform/core/dao/impl/VolumeUsageDaoTest.java b/code/iaas/auth-logic/src/test/java/io/cattle/platform/core/dao/impl/VolumeUsageDaoTest.java new file mode 100644 index 0000000000..4c399f53ac --- /dev/null +++ b/code/iaas/auth-logic/src/test/java/io/cattle/platform/core/dao/impl/VolumeUsageDaoTest.java @@ -0,0 +1,55 @@ +package io.cattle.platform.core.dao.impl; + +import static org.junit.Assert.*; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.util.List; +import io.cattle.platform.core.model.Mount; +import org.jooq.SQLDialect; +import org.jooq.conf.RenderQuotedNames; +import org.jooq.conf.Settings; +import org.jooq.impl.DSL; +import org.junit.Test; + +public class VolumeUsageDaoTest { + @Test public void nativeSqlBoundsRelationshipCandidatesBeforeMaterializationIncludingStoppedContainers() throws Exception { + try (Connection c = database()) { + var sql = DSL.using(c); sql.execute("insert into cattle.volume values(7,77,null)"); + for (int id = 1; id <= 70; id++) { + sql.execute("insert into cattle.instance values(?,77,'container',null,?)", id, id % 2 == 0 ? "running" : "stopped"); + sql.execute("insert into cattle.mount values(?,77,7,?,'/data','rw',null)", id, id); + } + VolumeDaoImpl dao = dao(c); List rows = dao.getUsageMounts(77, 7); + assertEquals(51, rows.size()); assertEquals(Long.valueOf(1), rows.getFirst().getInstanceId()); assertEquals(Long.valueOf(51), + rows.getLast().getInstanceId()); + } + } + + @Test public void nativeSqlExcludesEveryForeignRemovedAndNonContainerRelationshipWithoutWrites() throws Exception { + try (Connection c = database()) { + var sql = DSL.using(c); sql.execute("insert into cattle.volume values(7,77,null),(8,88,null),(9,77,current_timestamp)"); + sql.execute("insert into cattle.instance values(1,77,'container',null,'stopped')," + + "(2,88,'container',null,'running'),(3,77,'virtualMachine',null,'running')," + + "(4,77,'container',current_timestamp,'removed')"); + sql.execute("insert into cattle.mount values(1,77,7,1,'/data','ro',null),(2,77,7,2,'/foreign','rw',null)," + + "(3,77,7,3,'/vm','rw',null),(4,77,7,4,'/removed','rw',null),(5,88,7,1,'/foreign-owner','rw',null)," + + "(6,77,7,1,'/removed-mount','rw',current_timestamp),(7,77,8,1,'/foreign-volume','rw',null)," + + "(8,77,9,1,'/removed-volume','rw',null)"); + List rows = dao(c).getUsageMounts(77, 7); assertEquals(1, rows.size()); assertEquals("/data", rows.getFirst().getPath()); + assertTrue(dao(c).getUsageMounts(77, 8).isEmpty()); assertTrue(dao(c).getUsageMounts(77, 9).isEmpty()); + assertEquals(8, sql.fetchCount(DSL.table("cattle.mount"))); + } + } + + private static VolumeDaoImpl dao(Connection c) { VolumeDaoImpl d = new VolumeDaoImpl(); d.setConfiguration(DSL.using(c, SQLDialect.H2, + new Settings().withRenderQuotedNames(RenderQuotedNames.NEVER)).configuration()); return d; } + private static Connection database() throws Exception { + Connection c = DriverManager.getConnection("jdbc:h2:mem:" + java.util.UUID.randomUUID()); var sql = DSL.using(c); + sql.execute("create schema cattle"); + sql.execute("create table cattle.volume(id bigint,account_id bigint,removed timestamp)"); + sql.execute("create table cattle.instance(id bigint,account_id bigint,kind varchar,removed timestamp,state varchar)"); + sql.execute("create table cattle.mount(id bigint,account_id bigint,volume_id bigint,instance_id bigint," + + "path varchar,permissions varchar,removed timestamp)"); return c; + } +} diff --git a/code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/view/AiVolumeUsageViewTest.java b/code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/view/AiVolumeUsageViewTest.java new file mode 100644 index 0000000000..0d95035d84 --- /dev/null +++ b/code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/view/AiVolumeUsageViewTest.java @@ -0,0 +1,266 @@ +package io.cattle.platform.iaas.api.auth.ai.view; + +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import io.cattle.platform.api.auth.ApiKeyAuditSink; +import io.cattle.platform.core.dao.VolumeDao; +import io.cattle.platform.core.model.Mount; +import io.cattle.platform.core.model.tables.records.MountRecord; +import io.cattle.platform.core.model.tables.records.VolumeRecord; +import io.cattle.platform.core.model.tables.records.InstanceRecord; +import io.cattle.platform.core.model.tables.records.StackRecord; +import io.github.ibuildthecloud.gdapi.model.Field; +import io.cattle.platform.iaas.api.auth.apikey.ApiKeyAuthorizationService; +import io.cattle.platform.iaas.api.auth.apikey.ApiKeyCredentialContext; +import io.cattle.platform.iaas.api.auth.apikey.ApiKeyPolicy; +import io.cattle.platform.iaas.api.auth.apikey.ApiKeyPolicyEvaluator; +import io.cattle.platform.iaas.api.auth.apikey.ApiKeyTargetResolver; +import io.github.ibuildthecloud.gdapi.context.ApiContext; +import io.github.ibuildthecloud.gdapi.exception.ClientVisibleException; +import io.github.ibuildthecloud.gdapi.model.Resource; +import io.github.ibuildthecloud.gdapi.model.impl.ResourceImpl; +import io.github.ibuildthecloud.gdapi.request.ApiRequest; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.junit.After; +import org.junit.Test; + +public class AiVolumeUsageViewTest { + @After public void cleanup() { ApiContext.remove(); } + + @Test public void activeAndStoppedSameNameReferencesUseFreshOwnersAndAuthorizedStackNames() { + Fixture f = new Fixture(); f.mounts.add(mount(1, 11, "ro")); f.mounts.add(mount(2, 12, "rw")); + f.resources.put("container:11", resource("11", "container", "running", Map.of("stackId", "31"))); + f.resources.put("container:12", resource("12", "container", "stopped", Map.of("stackId", "32"))); + f.resources.put("stack:31", resource("31", "stack", "active", Map.of("name", "Blue"))); + f.resources.put("stack:32", resource("32", "stack", "active", Map.of("name", "Green"))); + List refs = references(f.read()); assertEquals(2, refs.size()); + assertEquals("Blue", ((Map) refs.get(0)).get("stackName")); + assertEquals("Green", ((Map) refs.get(1)).get("stackName")); + assertEquals(true, ((Map) refs.get(0)).get("readOnly")); + assertEquals("stopped", ((Map) refs.get(1)).get("state")); + assertFalse(refs.toString().contains("PRIVATE")); + verify(f.service.keyAuthorization, times(5)).actor(any()); + assertSame(f.originalContext, ApiContext.getContext().getApiRequest()); + } + + @Test public void hiddenForeignRemovedOrUnreadableParentsNeverExposeIdentitiesOrCounts() { + Fixture f = new Fixture(); + for (int id = 11; id <= 14; id++) f.mounts.add(mount(id, id, "rw")); + f.resources.put("container:11", resource("11", "container", "stopped", Map.of("stackId", "31"))); + f.resources.put("container:12", resource("12", "container", "running", Map.of("accountId", "88", "name", "PRIVATE_FOREIGN"))); + f.resources.put("container:13", resource("13", "container", "removed", Map.of("removed", "yesterday", "name", "PRIVATE_REMOVED"))); + f.resources.put("container:14", resource("14", "container", "running", Map.of("name", "PRIVATE_DENIED"))); + f.nativeScope = (type, id) -> !"14".equals(id); + Map result = f.read(); assertEquals(1, references(result).size()); + assertFalse(result.toString().contains("PRIVATE")); assertFalse(result.containsKey("hiddenCount")); + assertEquals("unknown", result.get("usageReferencesStatus")); + assertEquals("unknown", ((Map) references(result).getFirst()).get("stackResolution")); + verify(f.manager).getById(eq("container"), eq("14"), any()); + } + + @Test public void boundedSnapshotAndEmptyOrLegacyMetadataNeverClaimUnusedOrComplete() { + Fixture f = new Fixture(); + for (int id = 1; id <= 51; id++) { f.mounts.add(mount(id, 100 + id, "rw")); f.resources.put("container:" + (100 + id), + resource("" + (100 + id), "container", "stopped", Map.of())); } + Map result = f.read(); assertEquals(50, references(result).size()); assertEquals("unknown", result.get("usageReferencesStatus")); + verify(f.manager, never()).getById(eq("container"), eq("151"), any()); + f.mounts.clear(); result = f.read(); assertEquals(List.of(), references(result)); assertEquals("unknown", result.get("usageReferencesStatus")); + f.service.read(f.request(Map.of("resourceType", "volume"))); verify(f.dao, times(2)).getUsageMounts(77, 7); + assertFalse(AiResourceViewService.project("volume", "7", Map.of("mounts", List.of("PRIVATE"))).containsKey("usageReferences")); + } + + @Test public void realCustomKeyOwnerAuditsAllowAndDenyWithReadOnlyDispatchAndNoExtraGrant() throws Exception { + Fixture f = new Fixture(); f.mounts.add(mount(1, 11, "rw")); f.mounts.add(mount(2, 12, "ro")); + f.resources.put("container:11", resource("11", "container", "stopped", Map.of())); + f.resources.put("container:12", resource("12", "container", "running", Map.of("name", "PRIVATE_DENIED"))); + ApiKeyAuthorizationService access = new ApiKeyAuthorizationService(); ApiKeyTargetResolver targets = mock(ApiKeyTargetResolver.class); + List decisions = new ArrayList<>(); ApiKeyAuditSink sink = mock(ApiKeyAuditSink.class); + doAnswer(call -> { + ApiRequest r = call.getArgument(0); assertEquals("GET", r.getMethod()); + assertEquals("read", r.getAttribute("apiKey.audit.operation")); + assertEquals("5", r.getAttribute("apiKey.audit.keyId")); assertEquals(3L, r.getAttribute("apiKey.audit.policyRevision")); + assertEquals(42L, r.getAttribute("apiKey.audit.verifiedPrincipalAccountId")); assertSame(f.live, call.getArgument(1)); + decisions.add(r.getType() + ":" + r.getId() + ":" + r.getAttribute("apiKey.audit.decision")); return null; + }).when(sink).recordDecision(any(), any()); + field(access, "targets", targets); field(access, "auditSinks", List.of(sink)); + when(targets.resolve(any(), any())).thenAnswer(call -> { ApiRequest r = call.getArgument(0); + return List.of(ApiKeyPolicyEvaluator.Target.projectResource(r.getType(), r.getId(), "77")); }); + when(targets.stackLifecycleTargets(any(), any())).thenReturn(List.of()); when(targets.references(any(), any())).thenReturn(List.of()); + when(targets.parseScopeId(anyString(), anyString())).thenAnswer(call -> Long.valueOf(call.getArgument(1))); + f.service.keyAccess = access; + ApiKeyPolicy policy = new ApiKeyPolicy(ApiKeyPolicy.Mode.CUSTOM, ApiKeyPolicy.Effect.DENY, null, List.of( + new ApiKeyPolicy.Rule("volume", ApiKeyPolicy.Effect.ALLOW, ApiKeyPolicy.Scope.resource("volume", "7"), Set.of("read")), + new ApiKeyPolicy.Rule("container", ApiKeyPolicy.Effect.ALLOW, ApiKeyPolicy.Scope.resource("container", "11"), Set.of("read")))); + ApiKeyCredentialContext key = new ApiKeyCredentialContext(5, 42, "apiKey", 3, policy); + try (var c = java.sql.DriverManager.getConnection("jdbc:h2:mem:" + java.util.UUID.randomUUID())) { + var sql = org.jooq.impl.DSL.using(c, org.jooq.SQLDialect.H2, + new org.jooq.conf.Settings().withRenderQuotedNames(org.jooq.conf.RenderQuotedNames.NEVER)); + sql.execute("create schema cattle"); + sql.execute("create table cattle.instance(id bigint,account_id bigint,environment_id bigint,service_id bigint)"); + sql.execute("create table cattle.service(id bigint,account_id bigint,environment_id bigint,removed timestamp)"); + sql.execute("create table cattle.service_expose_map(id bigint,account_id bigint,instance_id bigint,service_id bigint," + + "managed boolean,upgrade boolean,removed timestamp)"); + sql.execute("insert into cattle.instance values(11,77,null,null),(12,77,null,null)"); + f.nativeScope = (type, id) -> { + if (!"container".equals(type)) return true; + var table = io.cattle.platform.core.model.tables.InstanceTable.INSTANCE; + var restriction = access.constrain(ApiContext.getContext().getApiRequest(), f.schemas, "instance", table); + return sql.fetchExists(sql.selectOne().from(table).where(table.ID.eq(Long.valueOf(id))).and(restriction)); + }; + ApiRequest request = f.request(Map.of("resourceType", "volume", "resourceId", "7")); ApiKeyCredentialContext.attach(request, key); + Map result = (Map) ((List) f.service.read(request).get("data")).getFirst(); + assertEquals(1, references(result).size()); assertFalse(result.toString().contains("PRIVATE_DENIED")); + assertEquals(List.of("volume:7:ALLOW"), decisions); // No hidden target ID/count enters audit. + verify(f.manager).getById(eq("container"), eq("12"), any()); + ApiRequest direct = new ApiRequest(null, f.schemas); direct.setType("container"); direct.setId("12"); direct.setMethod("GET"); + ApiKeyCredentialContext.attach(direct, key); + assertThrows(ClientVisibleException.class, () -> access.authorize(direct, f.live)); + assertEquals(List.of("volume:7:ALLOW", "container:12:DENY"), decisions); // Client supplied this exact target. + } + } + + @Test public void unattestedCustomKeyManagerReturnsUnknownWithoutTargetInspectionOrFallback() { + Fixture f = new Fixture(); f.mounts.add(mount(1, 11, "rw")); + ApiRequest request = f.request(Map.of("resourceType", "volume", "resourceId", "7")); + ApiKeyCredentialContext.attach(request, new ApiKeyCredentialContext(5, 42, "apiKey", 3, + new ApiKeyPolicy(ApiKeyPolicy.Mode.CUSTOM, ApiKeyPolicy.Effect.ALLOW, null, List.of()))); + when(f.manager.supportsScopedCollectionQuery(any())).thenReturn(false); + Map row = (Map) ((List) f.service.read(request).get("data")).getFirst(); + assertEquals("unknown", row.get("usageReferencesStatus")); assertTrue(references(row).isEmpty()); + verify(f.manager, never()).getById(eq("container"), anyString(), any()); + } + + @Test public void laterTargetKeyRevisionRevocationAbortsTheWholeReadAndRestoresContext() { + Fixture f = new Fixture(); f.mounts.add(mount(1, 11, "rw")); f.mounts.add(mount(2, 12, "rw")); + f.resources.put("container:11", resource("11", "container", "stopped", Map.of())); + when(f.service.keyAuthorization.actor(any())).thenReturn(f.owner, f.owner).thenThrow(new ClientVisibleException(403, "ApiKeyPolicyChanged")); + ClientVisibleException rejected = assertThrows(ClientVisibleException.class, f::read); + assertEquals("ApiKeyPolicyChanged", rejected.getCode()); + verify(f.manager, never()).getById(eq("container"), eq("12"), any()); + assertSame(f.originalContext, ApiContext.getContext().getApiRequest()); + assertSame(f.owner, ApiContext.getContext().getPolicy()); + } + + @Test public void nativeCoreProjectionRetainsSchemaFieldVisibilityAndNeverInvokesDtoAugmentation() { + Fixture f = new Fixture(); f.mounts.add(mount(1, 11, "rw")); + f.resources.put("container:11", resource("11", "container", "stopped", Map.of("stackId", "31"))); + f.resources.put("stack:31", resource("31", "stack", "active", Map.of("name", "Blue"))); + Field state = f.fields.get("state"); when(state.isReadOnCreateOnly()).thenReturn(true); + assertTrue(references(f.read()).isEmpty()); + when(state.isReadOnCreateOnly()).thenReturn(false); f.fields.remove("stackId"); + Map result = f.read(); assertEquals(1, references(result).size()); + assertFalse(result.toString().contains("Blue")); + assertEquals("unknown", ((Map) references(result).getFirst()).get("stackResolution")); + f.fields.remove("name"); assertTrue(references(f.read()).isEmpty()); + verify(f.manager, never()).convertResponse(any(Object.class), any()); + } + + @Test public void volumeScalarsMatchOriginalNativeWrappingForJwtFullAndLegacyIncludingSchemaAliasesAndTransforms() { + for (int mode = 0; mode < 3; mode++) { + Fixture f = new Fixture(); + VolumeRecord volume = new VolumeRecord(); volume.setId(7L); volume.setAccountId(77L); + volume.setName("named-volume"); volume.setDescription("kept description"); volume.setState("active"); volume.setKind("volume"); + volume.setSizeMb(8192L); + volume.setData(Map.of("fields", Map.of("driver", "persisted-driver", "isHostPath", false, "isNative", true, + "accessMode", "persisted-access", "launchConfig", Map.of("secret", "NEVER_COPY")))); + f.nativeRows.put("volume:7", volume); + for (String name : List.of("driver", "accessMode", "sizeMb", "created", "isNative", "isHostPath")) { + Field field = mock(Field.class); when(field.isIncludeInList()).thenReturn(true); + when(field.getTypeEnum()).thenReturn(io.github.ibuildthecloud.gdapi.model.FieldType.STRING); + Object value = "sizeMb".equals(name) ? 8192L : "isNative".equals(name) ? true : "isHostPath".equals(name) ? false + : "created".equals(name) ? "2026-11-05T00:00:00Z" : "native-" + name; + when(field.getValue(volume)).thenReturn(value); f.fields.put(name, field); + } + var fullSchema = new io.github.ibuildthecloud.gdapi.model.impl.SchemaImpl(); fullSchema.setId("volume"); fullSchema.setResourceFields(f.fields); + var oldNative = new io.github.ibuildthecloud.gdapi.model.impl.WrappedResource( + ApiContext.getContext().getIdFormatter(), f.schemas, fullSchema, volume, + new LinkedHashMap<>(io.cattle.platform.object.util.DataUtils.getFields(volume)), Set.of(), "GET", false); + Map expected = AiResourceViewService.project("volume", oldNative.getId(), oldNative.getFields()); + expected.put("sizeMb", oldNative.getFields().get("sizeMb")); + expected.put("isNative", oldNative.getFields().get("isNative")); expected.put("isHostPath", oldNative.getFields().get("isHostPath")); + ApiRequest request = f.request(Map.of("resourceType", "volume", "resourceId", "7")); + if (mode != 0) ApiKeyCredentialContext.attach(request, new ApiKeyCredentialContext(5, 42, "apiKey", 3, + mode == 1 ? new ApiKeyPolicy(ApiKeyPolicy.Mode.FULL, ApiKeyPolicy.Effect.ALLOW, null, List.of()) : null)); + Map actual = new LinkedHashMap<>((Map) ((List) f.service.read(request).get("data")).getFirst()); + actual.remove("usageReferences"); actual.remove("usageReferencesStatus"); + assertEquals(expected, actual); assertEquals("persisted-driver", actual.get("driver")); + assertEquals(true, actual.get("isNative")); assertEquals(false, actual.get("isHostPath")); + assertEquals(8192L, actual.get("sizeMb")); assertEquals("2026-11-05T00:00:00Z", actual.get("created")); + verify(f.manager, never()).convertResponse(any(Object.class), any()); + Field sensitive = f.fields.get("driver"); clearInvocations(sensitive); + when(sensitive.getTransform()).thenReturn("native-sensitive-transform"); + Map redacted = (Map) ((List) f.service.read(request).get("data")).getFirst(); + assertFalse(redacted.containsKey("driver")); verify(sensitive, never()).getValue(any()); + when(f.fields.get("isHostPath").isReadOnCreateOnly()).thenReturn(true); + Map createOnly = (Map) ((List) f.service.read(request).get("data")).getFirst(); + assertFalse(createOnly.containsKey("isHostPath")); assertFalse(createOnly.containsKey("launchConfig")); + } + } + + private static void field(Object owner, String name, Object value) throws Exception { var f = owner.getClass().getDeclaredField(name); + f.setAccessible(true); f.set(owner, value); } + private static List references(Map row) { return (List) row.get("usageReferences"); } + private static Mount mount(long id, long container, String permissions) { MountRecord row = new MountRecord(); row.setId(id); + row.setVolumeId(7L); row.setInstanceId(container); row.setPath("/data"); row.setPermissions(permissions); return row; } + private static Resource resource(String id, String type, String state, Map extra) { Map fields = new LinkedHashMap<>(Map.of("accountId", "77", "name", "same", "state", state, "launchConfig", "PRIVATE", "hostPath", + "PRIVATE")); fields.putAll(extra); return new ResourceImpl(id, type, fields); } + static class Fixture extends AiResourceViewServiceTest.Fixture { + final VolumeDao dao = mock(VolumeDao.class); + final List mounts = new ArrayList<>(); + final Map resources = new LinkedHashMap<>(); + final Map nativeRows = new LinkedHashMap<>(); + final Map fields = new LinkedHashMap<>(); + java.util.function.BiPredicate nativeScope = (type, id) -> true; + Fixture() { + when(live.getAccountId()).thenReturn(77L); when(live.getAuthenticatedAsAccountId()).thenReturn(42L); + service.volumes = dao; when(dao.getUsageMounts(77, 7)).thenAnswer(call -> mounts); + when(manager.supportsScopedCollectionQuery(any())).thenReturn(true); + resources.put("volume:7", resource("7", "volume", "active", Map.of("mounts", "PRIVATE_UNBOUNDED"))); + when(schema.getResourceFields()).thenReturn(fields); + when(schema.getId()).thenAnswer(call -> ApiContext.getContext().getApiRequest().getType()); + for (String name : List.of("id", "name", "state", "stackId", "description", "kind")) { + Field field = mock(Field.class); when(field.isIncludeInList()).thenReturn(true); + when(field.getTypeEnum()).thenReturn(io.github.ibuildthecloud.gdapi.model.FieldType.STRING); + if ("stackId".equals(name)) { + when(field.getTypeEnum()).thenReturn(io.github.ibuildthecloud.gdapi.model.FieldType.REFERENCE); + when(field.getSubTypes()).thenReturn(List.of("stack")); + } + when(field.getValue(any())).thenAnswer(call -> { + Object value = call.getArgument(0); + return value.getClass().getMethod("get" + Character.toUpperCase(name.charAt(0)) + name.substring(1)).invoke(value); + }); fields.put(name, field); + } + when(manager.getById(anyString(), anyString(), any())).thenAnswer(call -> { + String type = call.getArgument(0), id = call.getArgument(1); + if (!nativeScope.test(type, id)) return null; + if (nativeRows.containsKey(type + ":" + id)) return nativeRows.get(type + ":" + id); + Resource r = resources.get(type + ":" + id); + if (r == null) return null; + Long account = Long.valueOf(r.getFields().get("accountId").toString()); + java.util.Date removed = r.getFields().get("removed") == null ? null : new java.util.Date(); + if ("volume".equals(type)) { + VolumeRecord v = new VolumeRecord(); v.setId(Long.valueOf(r.getId())); v.setAccountId(account); + v.setName(r.getFields().get("name").toString()); v.setState(r.getFields().get("state").toString()); + v.setRemoved(removed); return v; + } + if ("container".equals(type)) { + InstanceRecord v = new InstanceRecord(); v.setId(Long.valueOf(r.getId())); v.setAccountId(account); v.setKind("container"); + v.setName(r.getFields().get("name").toString()); v.setState(r.getFields().get("state").toString()); v.setRemoved(removed); + if (r.getFields().get("stackId") != null) v.setStackId(Long.valueOf(r.getFields().get("stackId").toString())); return v; + } + StackRecord v = new StackRecord(); v.setId(Long.valueOf(r.getId())); v.setAccountId(account); + v.setName(r.getFields().get("name").toString()); v.setState(r.getFields().get("state").toString()); v.setRemoved(removed); return v; + }); + } + Map read() { + return (Map) ((List) service.read(request(Map.of("resourceType", "volume", "resourceId", "7"))).get("data")).getFirst(); + } + } +} diff --git a/code/iaas/bootstrap/pom.xml b/code/iaas/bootstrap/pom.xml index 9a97f8db41..307e59ccc9 100644 --- a/code/iaas/bootstrap/pom.xml +++ b/code/iaas/bootstrap/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/config-item/api/pom.xml b/code/iaas/config-item/api/pom.xml index ff5f9a6d5b..85744f2c96 100644 --- a/code/iaas/config-item/api/pom.xml +++ b/code/iaas/config-item/api/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/iaas/config-item/common/pom.xml b/code/iaas/config-item/common/pom.xml index fc6d23edd5..3b8874e7a3 100644 --- a/code/iaas/config-item/common/pom.xml +++ b/code/iaas/config-item/common/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/iaas/config-item/server/pom.xml b/code/iaas/config-item/server/pom.xml index 5e2c0e0090..36bb69f51c 100644 --- a/code/iaas/config-item/server/pom.xml +++ b/code/iaas/config-item/server/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/iaas/engine-jooq/pom.xml b/code/iaas/engine-jooq/pom.xml index 0b859f479b..2272a61107 100644 --- a/code/iaas/engine-jooq/pom.xml +++ b/code/iaas/engine-jooq/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/events/pom.xml b/code/iaas/events/pom.xml index d5596e4c5d..9cdf1b28cf 100644 --- a/code/iaas/events/pom.xml +++ b/code/iaas/events/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/external-handler/pom.xml b/code/iaas/external-handler/pom.xml index a874a01957..ffb0514177 100644 --- a/code/iaas/external-handler/pom.xml +++ b/code/iaas/external-handler/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/ha/pom.xml b/code/iaas/ha/pom.xml index 55765a82d2..04e2d117ed 100644 --- a/code/iaas/ha/pom.xml +++ b/code/iaas/ha/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/healthcheck/pom.xml b/code/iaas/healthcheck/pom.xml index 6319d017e3..526c28c22c 100644 --- a/code/iaas/healthcheck/pom.xml +++ b/code/iaas/healthcheck/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/labels/pom.xml b/code/iaas/labels/pom.xml index 5d4b4d2039..4ecb48131c 100644 --- a/code/iaas/labels/pom.xml +++ b/code/iaas/labels/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/logic-common/pom.xml b/code/iaas/logic-common/pom.xml index c3dcfc64e4..aec2f15ca2 100644 --- a/code/iaas/logic-common/pom.xml +++ b/code/iaas/logic-common/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/logic/pom.xml b/code/iaas/logic/pom.xml index faf40937d7..658497dc0c 100644 --- a/code/iaas/logic/pom.xml +++ b/code/iaas/logic/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/metadata/pom.xml b/code/iaas/metadata/pom.xml index 100a05b6ea..24e25c6e30 100644 --- a/code/iaas/metadata/pom.xml +++ b/code/iaas/metadata/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/model/pom.xml b/code/iaas/model/pom.xml index f21574c81d..4f476f4873 100644 --- a/code/iaas/model/pom.xml +++ b/code/iaas/model/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/model/src/main/java/io/cattle/platform/core/dao/VolumeDao.java b/code/iaas/model/src/main/java/io/cattle/platform/core/dao/VolumeDao.java index 605a690d06..fc5300cba2 100644 --- a/code/iaas/model/src/main/java/io/cattle/platform/core/dao/VolumeDao.java +++ b/code/iaas/model/src/main/java/io/cattle/platform/core/dao/VolumeDao.java @@ -36,6 +36,9 @@ public interface VolumeDao { Map> getMountsForVolumes(List ids, IdFormatter idF); + /** Bounded relationship candidates only; callers must authorize each container. */ + List getUsageMounts(long accountId, long volumeId); + List identifyUnmappedVolumes(long accountId, Set volumeIds); List findNonRemovedVolumesOnPool(Long storagePoolId); diff --git a/code/iaas/model/src/main/java/io/cattle/platform/core/dao/impl/VolumeDaoImpl.java b/code/iaas/model/src/main/java/io/cattle/platform/core/dao/impl/VolumeDaoImpl.java index 06e552f775..6f9891bbef 100644 --- a/code/iaas/model/src/main/java/io/cattle/platform/core/dao/impl/VolumeDaoImpl.java +++ b/code/iaas/model/src/main/java/io/cattle/platform/core/dao/impl/VolumeDaoImpl.java @@ -280,6 +280,23 @@ public Map> getMountsForVolumes(List ids, final IdF return result; } + @Override + public List getUsageMounts(long accountId, long volumeId) { + return create().select(MOUNT.ID, MOUNT.VOLUME_ID, MOUNT.INSTANCE_ID, MOUNT.PATH, MOUNT.PERMISSIONS) + .from(MOUNT) + .join(INSTANCE).on(INSTANCE.ID.eq(MOUNT.INSTANCE_ID)) + .join(VOLUME).on(VOLUME.ID.eq(MOUNT.VOLUME_ID)) + .where(MOUNT.VOLUME_ID.eq(volumeId)) + .and(MOUNT.ACCOUNT_ID.eq(accountId)) + .and(INSTANCE.ACCOUNT_ID.eq(accountId)) + .and(VOLUME.ACCOUNT_ID.eq(accountId)) + .and(INSTANCE.KIND.eq("container")) + .and(MOUNT.REMOVED.isNull()) + .and(INSTANCE.REMOVED.isNull()) + .and(VOLUME.REMOVED.isNull()) + .orderBy(MOUNT.ID.asc()).limit(51).fetchInto(MountRecord.class); + } + @Override public List findNonRemovedVolumesOnPool(Long storagePoolId) { return create().select(VOLUME.fields()) diff --git a/code/iaas/resource-pool/pom.xml b/code/iaas/resource-pool/pom.xml index 40aa437e39..f727aabbfb 100644 --- a/code/iaas/resource-pool/pom.xml +++ b/code/iaas/resource-pool/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/service-discovery/api/pom.xml b/code/iaas/service-discovery/api/pom.xml index fda64c8348..bb86f76794 100644 --- a/code/iaas/service-discovery/api/pom.xml +++ b/code/iaas/service-discovery/api/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/iaas/service-discovery/server/pom.xml b/code/iaas/service-discovery/server/pom.xml index b977346906..e29f77edf7 100644 --- a/code/iaas/service-discovery/server/pom.xml +++ b/code/iaas/service-discovery/server/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/iaas/ssh-common/pom.xml b/code/iaas/ssh-common/pom.xml index 8e2b4ab547..66bdb0a2fd 100644 --- a/code/iaas/ssh-common/pom.xml +++ b/code/iaas/ssh-common/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/storage-service/pom.xml b/code/iaas/storage-service/pom.xml index 3c7214e32b..6cc7411b30 100644 --- a/code/iaas/storage-service/pom.xml +++ b/code/iaas/storage-service/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/iaas/task-jooq/pom.xml b/code/iaas/task-jooq/pom.xml index 7f53885c97..8a52f7810a 100644 --- a/code/iaas/task-jooq/pom.xml +++ b/code/iaas/task-jooq/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/implementation/activity-log/pom.xml b/code/implementation/activity-log/pom.xml index 559eaf7ba7..eb26651792 100644 --- a/code/implementation/activity-log/pom.xml +++ b/code/implementation/activity-log/pom.xml @@ -5,7 +5,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/implementation/agent-instance-impl/pom.xml b/code/implementation/agent-instance-impl/pom.xml index c746ea5b07..adf076be13 100644 --- a/code/implementation/agent-instance-impl/pom.xml +++ b/code/implementation/agent-instance-impl/pom.xml @@ -3,7 +3,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml cattle-agent-instance-impl diff --git a/code/implementation/docker/api/pom.xml b/code/implementation/docker/api/pom.xml index 1bf7866c23..ebe8739007 100644 --- a/code/implementation/docker/api/pom.xml +++ b/code/implementation/docker/api/pom.xml @@ -5,7 +5,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/implementation/docker/common/pom.xml b/code/implementation/docker/common/pom.xml index 8ed018e9ea..98216c8b4e 100644 --- a/code/implementation/docker/common/pom.xml +++ b/code/implementation/docker/common/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/implementation/docker/compute/pom.xml b/code/implementation/docker/compute/pom.xml index 97b9bfa9f3..64365d9d3f 100644 --- a/code/implementation/docker/compute/pom.xml +++ b/code/implementation/docker/compute/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/implementation/docker/machine/pom.xml b/code/implementation/docker/machine/pom.xml index 08b2d5de8a..5660a0aade 100644 --- a/code/implementation/docker/machine/pom.xml +++ b/code/implementation/docker/machine/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/implementation/docker/storage/pom.xml b/code/implementation/docker/storage/pom.xml index 69c1b26fb1..375cd8e3e3 100644 --- a/code/implementation/docker/storage/pom.xml +++ b/code/implementation/docker/storage/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml @@ -21,12 +21,12 @@ io.cattle cattle-docker-common - 0.183.368 + 0.183.369 io.cattle cattle-iaas-allocator - 0.183.368 + 0.183.369 diff --git a/code/implementation/extension-api/pom.xml b/code/implementation/extension-api/pom.xml index 89ea22c627..b63929f0da 100644 --- a/code/implementation/extension-api/pom.xml +++ b/code/implementation/extension-api/pom.xml @@ -3,7 +3,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml cattle-extension-api diff --git a/code/implementation/hazelcast/common/pom.xml b/code/implementation/hazelcast/common/pom.xml index ff107a2036..b78fd309b5 100644 --- a/code/implementation/hazelcast/common/pom.xml +++ b/code/implementation/hazelcast/common/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/implementation/hazelcast/eventing/pom.xml b/code/implementation/hazelcast/eventing/pom.xml index 7b8d637996..bec314c33c 100644 --- a/code/implementation/hazelcast/eventing/pom.xml +++ b/code/implementation/hazelcast/eventing/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/implementation/hazelcast/lock/pom.xml b/code/implementation/hazelcast/lock/pom.xml index 5b96f93cdf..70cae8321e 100644 --- a/code/implementation/hazelcast/lock/pom.xml +++ b/code/implementation/hazelcast/lock/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/implementation/host-api/pom.xml b/code/implementation/host-api/pom.xml index e367671ec7..e571dcb596 100644 --- a/code/implementation/host-api/pom.xml +++ b/code/implementation/host-api/pom.xml @@ -5,7 +5,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/implementation/host-stats/pom.xml b/code/implementation/host-stats/pom.xml index 7c47ea2c09..77b2127eb5 100644 --- a/code/implementation/host-stats/pom.xml +++ b/code/implementation/host-stats/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/implementation/register/pom.xml b/code/implementation/register/pom.xml index 35e0d29d73..81a5cc3a24 100644 --- a/code/implementation/register/pom.xml +++ b/code/implementation/register/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/implementation/sample-setup/pom.xml b/code/implementation/sample-setup/pom.xml index f802062e56..0f30f955bd 100644 --- a/code/implementation/sample-setup/pom.xml +++ b/code/implementation/sample-setup/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/implementation/settings-api/pom.xml b/code/implementation/settings-api/pom.xml index e480161519..659e206e3b 100644 --- a/code/implementation/settings-api/pom.xml +++ b/code/implementation/settings-api/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/implementation/simulator/agent-connection/pom.xml b/code/implementation/simulator/agent-connection/pom.xml index c1d4575ef8..b532d9de07 100644 --- a/code/implementation/simulator/agent-connection/pom.xml +++ b/code/implementation/simulator/agent-connection/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/implementation/simulator/storage/pom.xml b/code/implementation/simulator/storage/pom.xml index 4a4449d17f..0a9cefeade 100644 --- a/code/implementation/simulator/storage/pom.xml +++ b/code/implementation/simulator/storage/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../../parent/pom.xml diff --git a/code/implementation/system-stack/pom.xml b/code/implementation/system-stack/pom.xml index c24b979c64..68aedb692f 100644 --- a/code/implementation/system-stack/pom.xml +++ b/code/implementation/system-stack/pom.xml @@ -5,7 +5,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/implementation/vm/pom.xml b/code/implementation/vm/pom.xml index ba930cf890..5bf7d79dad 100644 --- a/code/implementation/vm/pom.xml +++ b/code/implementation/vm/pom.xml @@ -3,7 +3,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml cattle-vm diff --git a/code/meta-parent/pom.xml b/code/meta-parent/pom.xml index 913243aefd..20450ce20c 100644 --- a/code/meta-parent/pom.xml +++ b/code/meta-parent/pom.xml @@ -9,7 +9,7 @@ 4.0.0 io.cattle cattle-meta-parent - 0.183.368 + 0.183.369 pom PastureStack Orchestration Engine Compatibility orchestration engine for the PastureStack server. diff --git a/code/packaging/app-config/pom.xml b/code/packaging/app-config/pom.xml index 65a777df6a..419a913ce2 100644 --- a/code/packaging/app-config/pom.xml +++ b/code/packaging/app-config/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml jar diff --git a/code/packaging/app/pom.xml b/code/packaging/app/pom.xml index 188daccd96..2a2a83ce97 100644 --- a/code/packaging/app/pom.xml +++ b/code/packaging/app/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml war diff --git a/code/packaging/bundle/pom.xml b/code/packaging/bundle/pom.xml index b2ac54d37e..4ab4449164 100644 --- a/code/packaging/bundle/pom.xml +++ b/code/packaging/bundle/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/packaging/dev/pom.xml b/code/packaging/dev/pom.xml index 568b38978f..522707672e 100644 --- a/code/packaging/dev/pom.xml +++ b/code/packaging/dev/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/packaging/meta/pom.xml b/code/packaging/meta/pom.xml index e445bc35dc..66d1dd9b49 100644 --- a/code/packaging/meta/pom.xml +++ b/code/packaging/meta/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../../parent/pom.xml diff --git a/code/parent/pom.xml b/code/parent/pom.xml index da256de182..9cd59d4f9b 100644 --- a/code/parent/pom.xml +++ b/code/parent/pom.xml @@ -5,7 +5,7 @@ io.cattle cattle-meta-parent ../meta-parent/pom.xml - 0.183.368 + 0.183.369 pom diff --git a/docs/releases/orchestration-engine-0.183.369.md b/docs/releases/orchestration-engine-0.183.369.md new file mode 100644 index 0000000000..df56c5d26b --- /dev/null +++ b/docs/releases/orchestration-engine-0.183.369.md @@ -0,0 +1,23 @@ +# Engine 0.183.369 candidate + +This candidate adds bounded Volume usage references to the existing read-only +typed resource detail. It is not published or runtime-qualified. Matching +Web Console 1.6.208 / bridge 0.2.10 and a new Server assembly are required. + +Native SQL reads at most 51 mount relationships and projects at most 50 +currently authorized active or stopped containers. Container destination paths +and read-only flags are safe metadata; host source paths, configuration, secrets +and hidden identities/counts are excluded. Current object/Key scope and +role-schema scalar visibility remain authoritative, including readable Stack +relationships. Ordinary DTO output filters and deletion oracles are unchanged. + +Completeness is always unknown. Empty or limited results never mean unused or +safe to delete. The existing outer read retains canonical audit; inaccessible +relationship targets create no synthetic API events. Direct denied requests +still retain their normal audit. No tools, grants or writes are added. + +Ten focused source methods cover native SQL bounds, ownership/scopes, audit, +reference metadata and scalar compatibility; all prior 132 required identities +are retained and ten new identities raise the release registry to 142. C03 +re-extraction retains 1396 tuples with zero operation/grant delta. Necessary +original CI, artifact qualification and native workflow acceptance remain pending. diff --git a/pom.xml b/pom.xml index 2d6bdb8bfb..a1a92f8fe0 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ io.cattle cattle-parent - 0.183.368 + 0.183.369 code/parent/pom.xml cattle diff --git a/resources/pom.xml b/resources/pom.xml index 5890917aaa..39db34a076 100644 --- a/resources/pom.xml +++ b/resources/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.368 + 0.183.369 ../code/parent/pom.xml diff --git a/scripts/api-key-operation-contract.json b/scripts/api-key-operation-contract.json index 52824595d2..2b7078d51b 100644 --- a/scripts/api-key-operation-contract.json +++ b/scripts/api-key-operation-contract.json @@ -9,8 +9,8 @@ "scope": "Declared v1/v2 and source handler/process union; source-only review, not current artifact packaging, live role/state availability or asynchronous completion.", "sourceInputs": { "algorithm": "c03-source-inputs-v1", - "count": 447, - "sha256": "da122b39e8ffac069b78d60c7234ff62cbb1995028efa835a7f717f8d02dee4c", + "count": 449, + "sha256": "5bbfd304067c39be44f7415ed00e654e2386ef8827f618a2f13ef6ed1c7562a3", "anchors": [ "AbstractSchemaFactory.java", "AiAliasServiceChange.java", @@ -107,6 +107,8 @@ "ServiceValidationFilter.java", "TokenAuthLookup.java", "TransformInspect.java", + "VolumeDao.java", + "VolumeDaoImpl.java", "VolumePreflightInputs.java", "VolumePreflightService.java" ], @@ -251,106 +253,176 @@ "tupleCount": 1396, "tupleSha256": "8f1c0fb378663b0b3d272efba2f211cb210eb6f17cb8035aefa33b56feeaf36a", "extensionReview": { - "version": "unreleased-368-external-service-create-tcp-healthcheck", + "version": "unreleased-369-volume-usage-safe-read", "status": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", - "scope": "External Service CREATE accepts an optional closed TCP healthCheck subset through its existing typed plan owner. Exactly the five caller fields are reviewed; port is required 1..65535 and four omitted timing fields are not filled. The positive integer timing subset matches existing typed Service validation; native metadata declares no timing minimum or defaults. HTTP controls and unknown, null, wrong-type or fractional values are rejected. The detached native body alone carries requestLine=null. Native schema/role projection is rechecked before preparation and dispatch; exact TCP readback is required for a verified receipt. No UPDATE healthCheck support, new HTTP route, operation semantics, role/Key grant, or approval bypass. Omitted healthCheck retains None and ordinary Service health checks are unchanged.", + "scope": "Volume detail adds a read-only bounded usage-reference projection through the existing typed resource view. Native SQL retrieves at most 51 relationships before materialization and exposes at most 50 authorized container targets. Current native object authorization and an exact attested Key query scope remain mandatory; unsupported scoped managers return unknown. Hidden targets create no synthetic API/audit entries. The selected Volume read retains canonical audit and direct hidden-resource requests retain DENY audit. Closed scalar fields reuse native data-field precedence and current-role schema wrapping, excluding transformed/create-only fields before access; parent names require a readable persisted Stack relationship and a fresh authorized Stack read. Completeness is always unknown; no total, hidden identity/count, host source path, write, grant or deletion-oracle change.", "previous": { - "version": "unreleased-367-service-upgrade-strategy-audit-preview-native-action-lock-order-and-rollback-fence", + "version": "unreleased-368-external-service-create-tcp-healthcheck", "status": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", - "scope": "Complete published366/current367 production schema-handler-process unions were independently re-extracted. All1396 HTTP tuples, operation semantics and admission dispositions remain exact. Existing Service upgrade plans gain three bounded optional strategy inputs and a closed read-only effective strategy, with repeated native port/volume preflight and unchanged current role/Key/revision/claim checks. The typed preview checks its original closed field set and original three strategy values before native coercion, retaining only a sticky rejection boolean with unchanged serviceId/image and action semantics. The typed Audit owner preserves a boolean closed-input rejection before ordinary schema sanitization and records its existing canonical ERROR. No generic schema filtering, new public operation or global mutation grant. Native Catalog-launch, resource-change and upgrade action operands use only exact framework request markers and authorized read snapshots. No prefetch observation writes or retained plan/credential row locks precede the action application lock. Ordinary GET observation and final action owner, role, Key revision, source/snapshot, CAS and one-claim checks remain; no timeout, retry, schema or grant expansion. New upgrade plans bind the complete strategy in their private target snapshot so older engines reject them before claim; genuine legacy image-only plans keep classic snapshots and original defaults.", + "scope": "External Service CREATE accepts an optional closed TCP healthCheck subset through its existing typed plan owner. Exactly the five caller fields are reviewed; port is required 1..65535 and four omitted timing fields are not filled. The positive integer timing subset matches existing typed Service validation; native metadata declares no timing minimum or defaults. HTTP controls and unknown, null, wrong-type or fractional values are rejected. The detached native body alone carries requestLine=null. Native schema/role projection is rechecked before preparation and dispatch; exact TCP readback is required for a verified receipt. No UPDATE healthCheck support, new HTTP route, operation semantics, role/Key grant, or approval bypass. Omitted healthCheck retains None and ordinary Service health checks are unchanged.", "previous": { - "version": "unreleased-366-service-create-native-ports-healthcheck-and-catalog-projection", + "version": "unreleased-367-service-upgrade-strategy-audit-preview-native-action-lock-order-and-rollback-fence", "status": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", - "scope": "Complete 365/366 production schema-handler-process unions were independently re-extracted. All 1396 HTTP tuples, operation semantics and registered/unsupported dispositions remain exact. Existing typed Service create adds bounded ports/healthCheck inputs and reuses native preflight before preview/confirmation/claim; normal manager validation remains. Three current role projections add only read access to the new server-produced executionResult, with existing plan owner/current authorization and successful verified Service UUID binding retained. No existing role/action/CRUD grant is changed. Native IPv6 formatting and stricter create readback are functional changes, not new public operation grants. Environment/private human input remains unsupported. Nine direct native/helper source owners are explicitly bound. Catalog Materializer now supplies the native dynamic data.fields map to its existing current-role schema projection; real transformer/native-schema tests verify business values and hidden/create-only/unlisted field exclusions. Production-only selection and historical producer355 remain unchanged.", - "materializerDynamicProjection": { - "source": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchMaterializer.java", - "rootCause": "DockerTransformer stores imageUuid/environment/ports/logConfig in InstanceRecord data.fields; the five-argument WrappedResource constructor did not receive that dynamic value map, so the real role-schema projection omitted required business values.", - "fix": "Pass a fresh LinkedHashMap copy of DataUtils.getFields(instance) to the seven-argument WrappedResource constructor. Keep the existing current-role SchemaFactory, ID formatter, POST and createResponse=false behavior.", - "preservedBusinessValues": [ - "native docker imageUuid", - "environment exact scalar including embedded equals", - "fixed native ports", - "logConfig driver/config", - "bean-backed service name" - ], - "visibilityBoundary": "Current native role schema remains authoritative. Hidden environment, read-on-create-only ports/logConfig and unlisted dynamic fields remain absent; no role or Key authority expansion, raw bypass or new environment-input channel.", - "focusedTests": { - "newMethods": [ - "dynamicProjectionKeepsRestrictedSchemaAndNonCreateResponseRules", - "realTransformerDynamicFieldsReachNativeRoleSchemaProjection" - ], - "existingAffectedMethods": [ - "preparedGraphSeparatesNativeMutationFromAuthorizedPublicReferenceIds" - ], - "tests": 3, - "failures": 0, - "errors": 0, - "skipped": 0, - "evidenceFile": "engine366-materializer-dynamic-fields-focused-20261102.json", - "evidenceSha256": "24ea39c3caf6f6664735e67308246db34a07c59f384cccea48d9e2b171cbd35a", - "usesRealDockerTransformerAndNativeSchemas": true - }, - "runtimeAcceptance": "PENDING_MATCHING_ARTIFACT_AND_NATIVE_QA; no live pass claimed" - }, + "scope": "Complete published366/current367 production schema-handler-process unions were independently re-extracted. All1396 HTTP tuples, operation semantics and admission dispositions remain exact. Existing Service upgrade plans gain three bounded optional strategy inputs and a closed read-only effective strategy, with repeated native port/volume preflight and unchanged current role/Key/revision/claim checks. The typed preview checks its original closed field set and original three strategy values before native coercion, retaining only a sticky rejection boolean with unchanged serviceId/image and action semantics. The typed Audit owner preserves a boolean closed-input rejection before ordinary schema sanitization and records its existing canonical ERROR. No generic schema filtering, new public operation or global mutation grant. Native Catalog-launch, resource-change and upgrade action operands use only exact framework request markers and authorized read snapshots. No prefetch observation writes or retained plan/credential row locks precede the action application lock. Ordinary GET observation and final action owner, role, Key revision, source/snapshot, CAS and one-claim checks remain; no timeout, retry, schema or grant expansion. New upgrade plans bind the complete strategy in their private target snapshot so older engines reject them before claim; genuine legacy image-only plans keep classic snapshots and original defaults.", "previous": { - "version": "unreleased-365-catalog-private-native-wire-fix", + "version": "unreleased-366-service-create-native-ports-healthcheck-and-catalog-projection", "status": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", - "scope": "The fixed-JSON Catalog private-envelope consumer decodes exactly one canonical standard Base64 layer returned by the existing Go Secrets create/rewrap contract, then parses JSON and rechecks version plus exact plan/actor/project/original-Key binding. Global SecretsService.decrypt and its legacy consumers are unchanged. The decoded JSON remains limited to 512 KiB; Base64 wire has its separate 4*ceil(limit/3) bound. Malformed, nested, raw JSON, oversized or rebound input still produces the fixed safe 503. This adds no authorization relaxation. The prior substantive standalone cleanup authorization fix and Alias safe 422 validation remain unchanged; the whole 365 candidate is not zero authorization-semantic delta. Historical producer355 and complete previous reviews remain preserved.", + "scope": "Complete 365/366 production schema-handler-process unions were independently re-extracted. All 1396 HTTP tuples, operation semantics and registered/unsupported dispositions remain exact. Existing typed Service create adds bounded ports/healthCheck inputs and reuses native preflight before preview/confirmation/claim; normal manager validation remains. Three current role projections add only read access to the new server-produced executionResult, with existing plan owner/current authorization and successful verified Service UUID binding retained. No existing role/action/CRUD grant is changed. Native IPv6 formatting and stricter create readback are functional changes, not new public operation grants. Environment/private human input remains unsupported. Nine direct native/helper source owners are explicitly bound. Catalog Materializer now supplies the native dynamic data.fields map to its existing current-role schema projection; real transformer/native-schema tests verify business values and hidden/create-only/unlisted field exclusions. Production-only selection and historical producer355 remain unchanged.", + "materializerDynamicProjection": { + "source": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchMaterializer.java", + "rootCause": "DockerTransformer stores imageUuid/environment/ports/logConfig in InstanceRecord data.fields; the five-argument WrappedResource constructor did not receive that dynamic value map, so the real role-schema projection omitted required business values.", + "fix": "Pass a fresh LinkedHashMap copy of DataUtils.getFields(instance) to the seven-argument WrappedResource constructor. Keep the existing current-role SchemaFactory, ID formatter, POST and createResponse=false behavior.", + "preservedBusinessValues": [ + "native docker imageUuid", + "environment exact scalar including embedded equals", + "fixed native ports", + "logConfig driver/config", + "bean-backed service name" + ], + "visibilityBoundary": "Current native role schema remains authoritative. Hidden environment, read-on-create-only ports/logConfig and unlisted dynamic fields remain absent; no role or Key authority expansion, raw bypass or new environment-input channel.", + "focusedTests": { + "newMethods": [ + "dynamicProjectionKeepsRestrictedSchemaAndNonCreateResponseRules", + "realTransformerDynamicFieldsReachNativeRoleSchemaProjection" + ], + "existingAffectedMethods": [ + "preparedGraphSeparatesNativeMutationFromAuthorizedPublicReferenceIds" + ], + "tests": 3, + "failures": 0, + "errors": 0, + "skipped": 0, + "evidenceFile": "engine366-materializer-dynamic-fields-focused-20261102.json", + "evidenceSha256": "24ea39c3caf6f6664735e67308246db34a07c59f384cccea48d9e2b171cbd35a", + "usesRealDockerTransformerAndNativeSchemas": true + }, + "runtimeAcceptance": "PENDING_MATCHING_ARTIFACT_AND_NATIVE_QA; no live pass claimed" + }, "previous": { - "version": "unreleased-365-native-validation-cleanup-fixes", + "version": "unreleased-365-catalog-private-native-wire-fix", "status": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", - "scope": "The existing HTTP tuple union and operation classifications remain exact. Derived native standalone cleanup authorization changes substantively: a CUSTOM native container DELETE may finish only its original private device-0 OS allocation map after the exact verified instance.remove -> volume.remove (optionally volume.deallocate) scheduling spine. The live spine pins complete UUID/FK/owner references; detached work rechecks that same immutable edge and current actor, role, Key revision/expiry, root grant and explicit dependency DENY. Only this pinned job may read historical removing/removed/purging/purged Instance/Volume ancestors; generic resource resolvers, unbound old jobs and public grants are unchanged. Alias native validation exceptions preserve the established safe 422 InvalidBody response instead of becoming a 500; this adds no grant. This is not zero authorization-semantic delta. Historical producer355 is unchanged.", + "scope": "The fixed-JSON Catalog private-envelope consumer decodes exactly one canonical standard Base64 layer returned by the existing Go Secrets create/rewrap contract, then parses JSON and rechecks version plus exact plan/actor/project/original-Key binding. Global SecretsService.decrypt and its legacy consumers are unchanged. The decoded JSON remains limited to 512 KiB; Base64 wire has its separate 4*ceil(limit/3) bound. Malformed, nested, raw JSON, oversized or rebound input still produces the fixed safe 503. This adds no authorization relaxation. The prior substantive standalone cleanup authorization fix and Alias safe 422 validation remain unchanged; the whole 365 candidate is not zero authorization-semantic delta. Historical producer355 and complete previous reviews remain preserved.", "previous": { - "version": "unreleased-364-native-lifecycle-fixes", + "version": "unreleased-365-native-validation-cleanup-fixes", "status": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", - "scope": "Exact extraction retains the existing HTTP tuples and operation classifications. Derived native private-image cleanup authorization changes substantively: a CUSTOM container DELETE may authorize only its proven private OS-image/cache dependency graph under verified instance.remove and volume.remove execution frames, with current owner, Key revision, expiry, root grant and explicit dependency deny checks retained. External target reconciliation marks an absent or different exact desired hostname as a bad unit for existing expose-map cleanup, instead of throwing on null or retaining substring matches. This is not a zero authorization-semantic-delta claim. Historical producer identity is unchanged.", + "scope": "The existing HTTP tuple union and operation classifications remain exact. Derived native standalone cleanup authorization changes substantively: a CUSTOM native container DELETE may finish only its original private device-0 OS allocation map after the exact verified instance.remove -> volume.remove (optionally volume.deallocate) scheduling spine. The live spine pins complete UUID/FK/owner references; detached work rechecks that same immutable edge and current actor, role, Key revision/expiry, root grant and explicit dependency DENY. Only this pinned job may read historical removing/removed/purging/purged Instance/Volume ancestors; generic resource resolvers, unbound old jobs and public grants are unchanged. Alias native validation exceptions preserve the established safe 422 InvalidBody response instead of becoming a 500; this adds no grant. This is not zero authorization-semantic delta. Historical producer355 is unchanged.", "previous": { - "version": "unreleased-363-external-review-before", + "version": "unreleased-364-native-lifecycle-fixes", "status": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", - "scope": "External Service review before values read the existing hostname/externalIpAddresses dynamic data.fields using DataAccessor, retaining the existing safe displayed projection. No HTTP declaration, grant, operation classification, owner or CAS contract changes. Historical producer identity is unchanged.", + "scope": "Exact extraction retains the existing HTTP tuples and operation classifications. Derived native private-image cleanup authorization changes substantively: a CUSTOM container DELETE may authorize only its proven private OS-image/cache dependency graph under verified instance.remove and volume.remove execution frames, with current owner, Key revision, expiry, root grant and explicit dependency deny checks retained. External target reconciliation marks an absent or different exact desired hostname as a bad unit for existing expose-map cleanup, instead of throwing on null or retaining substring matches. This is not a zero authorization-semantic-delta claim. Historical producer identity is unchanged.", "previous": { - "version": "unreleased-362-service-index-cleanup", + "version": "unreleased-363-external-review-before", "status": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", - "scope": "The native Service planner and remove owner may schedule only exact serviceindex.remove cleanup under their original update/delete operation. Current actor/role/Key/revision/expiry/revocation, precise Index/Service/Stack UUID/account/FK pins and explicit child DENY remain required. First trusted scheduling binds private references; detached workers cannot invent them. No HTTP declaration, public ServiceIndex scope grant, method or operation classification is added or changed. Historical producer identity is unchanged.", + "scope": "External Service review before values read the existing hostname/externalIpAddresses dynamic data.fields using DataAccessor, retaining the existing safe displayed projection. No HTTP declaration, grant, operation classification, owner or CAS contract changes. Historical producer identity is unchanged.", "previous": { - "version": "unreleased-361-runtime-workflows", + "version": "unreleased-362-service-index-cleanup", "status": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", - "scope": "Certificate metadata uses the existing typed plan and native PUT. Durable typed decision audit admits exactly the reviewed native domains. The fixed audit CLI receives only a validated local operator upstream reconstructed from fixed HTTP(S)/loopback literals and a bounded numeric port; no credential environment or caller URL is admitted. Standalone Instance DELETE retains only its verified native remove -> retired NIC remove -> exact IP deactivate ownership graph, current actor/Key ceilings and explicit child DENY. Typed child AUTHORIZATION_DENIED remains terminal instead of UNKNOWN retries. No HTTP declaration or operation classification is added or changed; historical producer identity is unchanged.", + "scope": "The native Service planner and remove owner may schedule only exact serviceindex.remove cleanup under their original update/delete operation. Current actor/role/Key/revision/expiry/revocation, precise Index/Service/Stack UUID/account/FK pins and explicit child DENY remain required. First trusted scheduling binds private references; detached workers cannot invent them. No HTTP declaration, public ServiceIndex scope grant, method or operation classification is added or changed. Historical producer identity is unchanged.", "previous": { - "version": "unreleased-360-domains", + "version": "unreleased-361-runtime-workflows", "status": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", - "scope": "ExternalService and DNS Alias typed owner workflows add no raw HTTP route; exact dnsservice.setservicelinks is update, service factory/ownership checks remain native. One fixed audit-query read POST; existing safe-view source input expands to four closed native read sources. Complete baseline/current schema-handler-process unions are re-extracted. Exactly one existing dnsService.setservicelinks classification changes to update; all other existing tuples remain unchanged and producer history remains unchanged. No audit raw payload, management operation, serviceFull identity, SQL reader or arbitrary proxy is added.", + "scope": "Certificate metadata uses the existing typed plan and native PUT. Durable typed decision audit admits exactly the reviewed native domains. The fixed audit CLI receives only a validated local operator upstream reconstructed from fixed HTTP(S)/loopback literals and a bounded numeric port; no credential environment or caller URL is admitted. Standalone Instance DELETE retains only its verified native remove -> retired NIC remove -> exact IP deactivate ownership graph, current actor/Key ceilings and explicit child DENY. Typed child AUTHORIZATION_DENIED remains terminal instead of UNKNOWN retries. No HTTP declaration or operation classification is added or changed; historical producer identity is unchanged.", "previous": { - "version": "0.183.359", - "scope": "Source-only Catalog launch plus stopped-resource Archive/restore extension; Archive adds no HTTP declaration: full immutable 358 schema/handler/process union re-extracted. Historical producer unchanged. Fixed metadata/options reads and durable create-plan routes are new; only exact Service.setservicelinks changes to update. Typed launch still requires original live role and Key read/create/update at the destination, references, source CAS, Cookie-human-only completion/approval, normal managers and per-child exact-graph authorization. Neither classification nor local tests prove runtime acceptance.", + "version": "unreleased-360-domains", + "status": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", + "scope": "ExternalService and DNS Alias typed owner workflows add no raw HTTP route; exact dnsservice.setservicelinks is update, service factory/ownership checks remain native. One fixed audit-query read POST; existing safe-view source input expands to four closed native read sources. Complete baseline/current schema-handler-process unions are re-extracted. Exactly one existing dnsService.setservicelinks classification changes to update; all other existing tuples remain unchanged and producer history remains unchanged. No audit raw payload, management operation, serviceFull identity, SQL reader or arbitrary proxy is added.", "previous": { - "version": "0.183.358", - "scope": "Source-only managed lifecycle and native-name-query fixes. All 1386 HTTP declarations and semantic tuples are unchanged. Original producer identity is unchanged. Not runtime acceptance.", + "version": "0.183.359", + "scope": "Source-only Catalog launch plus stopped-resource Archive/restore extension; Archive adds no HTTP declaration: full immutable 358 schema/handler/process union re-extracted. Historical producer unchanged. Fixed metadata/options reads and durable create-plan routes are new; only exact Service.setservicelinks changes to update. Typed launch still requires original live role and Key read/create/update at the destination, references, source CAS, Cookie-human-only completion/approval, normal managers and per-child exact-graph authorization. Neither classification nor local tests prove runtime acceptance.", "previous": { - "version": "0.183.357", - "scope": "Source-only B1/B2 runtime read fixes. All 1386 HTTP declarations and semantic tuples are unchanged. Original producer identity is unchanged. Not runtime acceptance.", + "version": "0.183.358", + "scope": "Source-only managed lifecycle and native-name-query fixes. All 1386 HTTP declarations and semantic tuples are unchanged. Original producer identity is unchanged. Not runtime acceptance.", "previous": { - "version": "0.183.356", - "scope": "Source-only B1/B2 extension: re-extracted the complete baseline and current schema/handler/process union. Original producer identity is unchanged. Seven typed API tuples are added; only the two exact stack service actions change classification. Classification does not grant admission or prove asynchronous completion.", + "version": "0.183.357", + "scope": "Source-only B1/B2 runtime read fixes. All 1386 HTTP declarations and semantic tuples are unchanged. Original producer identity is unchanged. Not runtime acceptance.", "previous": { - "version": "0.183.355", - "scope": "The original 1371 operation tuples are unchanged. Eight declarations were re-extracted from the three explicit AI resource schemas and reviewed against ApiKeyOperations. Classification does not imply Key admission: plan collection GET is human-only, and confirm/cancel reject every API Key.", + "version": "0.183.356", + "scope": "Source-only B1/B2 extension: re-extracted the complete baseline and current schema/handler/process union. Original producer identity is unchanged. Seven typed API tuples are added; only the two exact stack service actions change classification. Classification does not grant admission or prove asynchronous completion.", + "previous": { + "version": "0.183.355", + "scope": "The original 1371 operation tuples are unchanged. Eight declarations were re-extracted from the three explicit AI resource schemas and reviewed against ApiKeyOperations. Classification does not imply Key admission: plan collection GET is human-only, and confirm/cancel reject every API Key.", + "schemas": [ + "resources/content/schema/base/aiServiceDescriptionUpdate.json", + "resources/content/schema/base/aiServiceUpgradePlan.json", + "resources/content/schema/base/aiToolCallEvent.json" + ], + "addedTuples": [ + [ + "aiServiceDescriptionUpdate", + "collection", + "POST", + "", + "", + "update" + ], + [ + "aiServiceUpgradePlan", + "collection", + "GET", + "", + "", + "read" + ], + [ + "aiServiceUpgradePlan", + "collection", + "POST", + "", + "", + "upgrade" + ], + [ + "aiServiceUpgradePlan", + "resource", + "GET", + "", + "", + "read" + ], + [ + "aiServiceUpgradePlan", + "resource", + "POST", + "confirm", + "", + "ai-plan:confirm" + ], + [ + "aiServiceUpgradePlan", + "resource", + "POST", + "apply", + "", + "upgrade" + ], + [ + "aiServiceUpgradePlan", + "resource", + "POST", + "cancel", + "", + "ai-plan:cancel" + ], + [ + "aiToolCallEvent", + "collection", + "POST", + "", + "", + "create" + ] + ] + }, "schemas": [ "resources/content/schema/base/aiServiceDescriptionUpdate.json", "resources/content/schema/base/aiServiceUpgradePlan.json", - "resources/content/schema/base/aiToolCallEvent.json" + "resources/content/schema/base/aiToolCallEvent.json", + "resources/content/schema/base/aiResourceView.json", + "resources/content/schema/base/aiResourceChangePlan.json" ], "addedTuples": [ [ - "aiServiceDescriptionUpdate", - "collection", - "POST", - "", - "", - "update" - ], - [ - "aiServiceUpgradePlan", + "aiResourceChangePlan", "collection", "GET", "", @@ -358,15 +430,15 @@ "read" ], [ - "aiServiceUpgradePlan", + "aiResourceChangePlan", "collection", "POST", "", "", - "upgrade" + "update" ], [ - "aiServiceUpgradePlan", + "aiResourceChangePlan", "resource", "GET", "", @@ -374,37 +446,134 @@ "read" ], [ - "aiServiceUpgradePlan", + "aiResourceChangePlan", "resource", "POST", - "confirm", + "apply", "", - "ai-plan:confirm" + "update" ], [ - "aiServiceUpgradePlan", + "aiResourceChangePlan", "resource", "POST", - "apply", + "cancel", "", - "upgrade" + "ai-change:cancel" ], [ - "aiServiceUpgradePlan", + "aiResourceChangePlan", "resource", "POST", - "cancel", + "confirm", "", - "ai-plan:cancel" + "ai-change:confirm" ], [ - "aiToolCallEvent", + "aiResourceView", "collection", "POST", "", "", - "create" + "read" ] + ], + "changedTuples": [ + { + "before": [ + "stack", + "resource", + "POST", + "activateservices", + "", + "action:activateservices" + ], + "after": [ + "stack", + "resource", + "POST", + "activateservices", + "", + "update" + ], + "rationale": "Existing Stack child-service lifecycle handler; fixed typed pair, live child authorization remains required." + }, + { + "before": [ + "stack", + "resource", + "POST", + "deactivateservices", + "", + "action:deactivateservices" + ], + "after": [ + "stack", + "resource", + "POST", + "deactivateservices", + "", + "update" + ], + "rationale": "Existing Stack child-service lifecycle handler; fixed typed pair, live child authorization remains required." + } + ], + "authorizationRationale": { + "aiResourceView": "Read semantic POST. Synthetic admission is followed by authorized domain reads and safe projection, never raw GET expansion.", + "aiResourceChangePlan": "Preview/apply are classified update admission only. Fixed domain adapter rechecks the actual create/update/delete operation and Key references. Collection GET and confirm/cancel are human-only; every Key is denied confirmation/cancellation.", + "stackServiceActions": "The two exact Stack batch actions preflight every persisted child with current owner and same-project/Stack checks. An authorized root grant is inherited only for dependency evaluation; explicit child DENY still wins before manager dispatch. The same recheck applies to human approval of bound-Key plans, and queued execution retains its independent live child checks. General Full and legacy admission paths are unchanged." + }, + "sourceInputChanges": [ + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyAuthorizationService.java", + "before": "8062f242159f18d5c21fc14ab65ce42c6cbb8a3bd6cb30dc0cb461bc9a282fbb", + "after": "9ceda0f5118d38fc45fc83bd4a16eb92717a20f7837bcabb804975600c59d2c5" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyOperations.java", + "before": "5b13ab34ee167596cc7f4b664dcc6afc6ab18f12442ed6d44a35b58ad08b40b9", + "after": "494a57d48564da85f14de564a82906444fa732f1adb201fe27d8c0ca88ea65e5" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", + "before": "391918c715b70d8fd9a607da01ac9acc85a1e3e04901c12cc21feb6ba1d98c2e", + "after": "b31333ffc5de2ec8fbee9d38daacd83b91578525d1fe1b61a73abac6355aa009" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanResourceManager.java", + "before": null, + "after": "37da81bdccdb528c1d7f1b18217d3896cabd0ad601e6a3809fd50913b6613050" + }, + { + "path": "resources/content/schema/admin/admin-auth.json", + "before": "be3f0ba2a4fa51a1c42fbf4fc7abe457b65420e8664301fa462474e015a6796f", + "after": "79a757118dd66055c6e7e4c03ded4b0dd8ef1965887c50a4c106e15836d4938f" + }, + { + "path": "resources/content/schema/base/aiResourceChangePlan.json", + "before": null, + "after": "ec4b5ceb31e42dceb71c2fb0f475daf868a19a08ad9644dcf17ee8c06c769786" + }, + { + "path": "resources/content/schema/base/aiResourceView.json", + "before": null, + "after": "024fb697f3d5e1ed511544ff6922f3b78c351f01e74df1a36faeee3e7f3dba95" + }, + { + "path": "resources/content/schema/base/aiToolCallEvent.json", + "before": "58333f82f8842bf13ed0780251a21000a0f59a56a1ef1bc4354dd03aca4cd7e8", + "after": "6d4cfccd6f4901d71e7ba8ec0818de0f769f3bd8e41794dc4ca9616a3794bfbf" + }, + { + "path": "resources/content/schema/project/project-auth.json", + "before": "c939bcf67064be956929820f561a5dde9512facf16eb18dc4f7910ab16e852c3", + "after": "96dcb3b12d6ba0a15e5532df71c68683b2fe87a8946ecb71c10109dea4f17585" + }, + { + "path": "resources/content/schema/user/user-auth.json", + "before": "9080a03720c6c9a9bdc84d3d9fb82ed5e2d0cbbcf16d5774a2a842d8677731f7", + "after": "91c44ff87f288c967d38cfe0c6c1dd04e4ac09919cd6c6ba8407806a61168a2f" + } ] }, "schemas": [ @@ -412,161 +581,24 @@ "resources/content/schema/base/aiServiceUpgradePlan.json", "resources/content/schema/base/aiToolCallEvent.json", "resources/content/schema/base/aiResourceView.json", - "resources/content/schema/base/aiResourceChangePlan.json" - ], - "addedTuples": [ - [ - "aiResourceChangePlan", - "collection", - "GET", - "", - "", - "read" - ], - [ - "aiResourceChangePlan", - "collection", - "POST", - "", - "", - "update" - ], - [ - "aiResourceChangePlan", - "resource", - "GET", - "", - "", - "read" - ], - [ - "aiResourceChangePlan", - "resource", - "POST", - "apply", - "", - "update" - ], - [ - "aiResourceChangePlan", - "resource", - "POST", - "cancel", - "", - "ai-change:cancel" - ], - [ - "aiResourceChangePlan", - "resource", - "POST", - "confirm", - "", - "ai-change:confirm" - ], - [ - "aiResourceView", - "collection", - "POST", - "", - "", - "read" - ] - ], - "changedTuples": [ - { - "before": [ - "stack", - "resource", - "POST", - "activateservices", - "", - "action:activateservices" - ], - "after": [ - "stack", - "resource", - "POST", - "activateservices", - "", - "update" - ], - "rationale": "Existing Stack child-service lifecycle handler; fixed typed pair, live child authorization remains required." - }, - { - "before": [ - "stack", - "resource", - "POST", - "deactivateservices", - "", - "action:deactivateservices" - ], - "after": [ - "stack", - "resource", - "POST", - "deactivateservices", - "", - "update" - ], - "rationale": "Existing Stack child-service lifecycle handler; fixed typed pair, live child authorization remains required." - } + "resources/content/schema/base/aiResourceChangePlan.json", + "resources/content/schema/base/processPool.json" ], + "addedTuples": [], + "changedTuples": [], "authorizationRationale": { - "aiResourceView": "Read semantic POST. Synthetic admission is followed by authorized domain reads and safe projection, never raw GET expansion.", - "aiResourceChangePlan": "Preview/apply are classified update admission only. Fixed domain adapter rechecks the actual create/update/delete operation and Key references. Collection GET and confirm/cancel are human-only; every Key is denied confirmation/cancellation.", - "stackServiceActions": "The two exact Stack batch actions preflight every persisted child with current owner and same-project/Stack checks. An authorized root grant is inherited only for dependency evaluation; explicit child DENY still wins before manager dispatch. The same recheck applies to human approval of bound-Key plans, and queued execution retains its independent live child checks. General Full and legacy admission paths are unchanged." + "runtimeReadFixes": "ProcessPool owner supplies stable executor bean identity, distinct from native null database IDs and nonunique display names; the opted-in metadata field is read-only and adds no methods. AI projects only its opaque digest. activeSetting is not a list-capable AI type; native schemas are unchanged. Existing domain validator-decoded decimal IDs are consumed directly as internal row IDs, while public parseScopeId retains strict wire round-trip and normal owner/Key grants/denials remain authoritative." }, "sourceInputChanges": [ - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyAuthorizationService.java", - "before": "8062f242159f18d5c21fc14ab65ce42c6cbb8a3bd6cb30dc0cb461bc9a282fbb", - "after": "9ceda0f5118d38fc45fc83bd4a16eb92717a20f7837bcabb804975600c59d2c5" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyOperations.java", - "before": "5b13ab34ee167596cc7f4b664dcc6afc6ab18f12442ed6d44a35b58ad08b40b9", - "after": "494a57d48564da85f14de564a82906444fa732f1adb201fe27d8c0ca88ea65e5" - }, { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", - "before": "391918c715b70d8fd9a607da01ac9acc85a1e3e04901c12cc21feb6ba1d98c2e", - "after": "b31333ffc5de2ec8fbee9d38daacd83b91578525d1fe1b61a73abac6355aa009" + "before": "b31333ffc5de2ec8fbee9d38daacd83b91578525d1fe1b61a73abac6355aa009", + "after": "fcd8d3724c1a37b2b77cab3e60ee3e973b349462833c1bf0bcc8f099d6f3567c" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanResourceManager.java", + "path": "resources/content/schema/base/processPool.json", "before": null, - "after": "37da81bdccdb528c1d7f1b18217d3896cabd0ad601e6a3809fd50913b6613050" - }, - { - "path": "resources/content/schema/admin/admin-auth.json", - "before": "be3f0ba2a4fa51a1c42fbf4fc7abe457b65420e8664301fa462474e015a6796f", - "after": "79a757118dd66055c6e7e4c03ded4b0dd8ef1965887c50a4c106e15836d4938f" - }, - { - "path": "resources/content/schema/base/aiResourceChangePlan.json", - "before": null, - "after": "ec4b5ceb31e42dceb71c2fb0f475daf868a19a08ad9644dcf17ee8c06c769786" - }, - { - "path": "resources/content/schema/base/aiResourceView.json", - "before": null, - "after": "024fb697f3d5e1ed511544ff6922f3b78c351f01e74df1a36faeee3e7f3dba95" - }, - { - "path": "resources/content/schema/base/aiToolCallEvent.json", - "before": "58333f82f8842bf13ed0780251a21000a0f59a56a1ef1bc4354dd03aca4cd7e8", - "after": "6d4cfccd6f4901d71e7ba8ec0818de0f769f3bd8e41794dc4ca9616a3794bfbf" - }, - { - "path": "resources/content/schema/project/project-auth.json", - "before": "c939bcf67064be956929820f561a5dde9512facf16eb18dc4f7910ab16e852c3", - "after": "96dcb3b12d6ba0a15e5532df71c68683b2fe87a8946ecb71c10109dea4f17585" - }, - { - "path": "resources/content/schema/user/user-auth.json", - "before": "9080a03720c6c9a9bdc84d3d9fb82ed5e2d0cbbcf16d5774a2a842d8677731f7", - "after": "91c44ff87f288c967d38cfe0c6c1dd04e4ac09919cd6c6ba8407806a61168a2f" + "after": "d055fc0e3bc30ffeb9567ca6a2c8cee7b7382200fe410c2e6154353305134b1b" } ] }, @@ -581,18 +613,14 @@ "addedTuples": [], "changedTuples": [], "authorizationRationale": { - "runtimeReadFixes": "ProcessPool owner supplies stable executor bean identity, distinct from native null database IDs and nonunique display names; the opted-in metadata field is read-only and adds no methods. AI projects only its opaque digest. activeSetting is not a list-capable AI type; native schemas are unchanged. Existing domain validator-decoded decimal IDs are consumed directly as internal row IDs, while public parseScopeId retains strict wire round-trip and normal owner/Key grants/denials remain authoritative." + "managedLifecycle": "Closed engine-captured scheduling edges preserve exact managed retirement ancestry while live owner/Key/revision/explicit-DENY remains authoritative; ordinary ancestry is not broadened and named/file storage does not inherit destructive removal.", + "nativeNameSearch": "Closed native name conditions narrow the already-authorized owner query before its bounded page; literal query and cursor/parent restrictions are retained. Memory projections filter before taking a page." }, "sourceInputChanges": [ { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", - "before": "b31333ffc5de2ec8fbee9d38daacd83b91578525d1fe1b61a73abac6355aa009", - "after": "fcd8d3724c1a37b2b77cab3e60ee3e973b349462833c1bf0bcc8f099d6f3567c" - }, - { - "path": "resources/content/schema/base/processPool.json", - "before": null, - "after": "d055fc0e3bc30ffeb9567ca6a2c8cee7b7382200fe410c2e6154353305134b1b" + "before": "fcd8d3724c1a37b2b77cab3e60ee3e973b349462833c1bf0bcc8f099d6f3567c", + "after": "645652a1352b74cf6ad4c2b1a9bbdfee1d168cef9df7c59e459d84c17d547c17" } ] }, @@ -602,19 +630,319 @@ "resources/content/schema/base/aiToolCallEvent.json", "resources/content/schema/base/aiResourceView.json", "resources/content/schema/base/aiResourceChangePlan.json", - "resources/content/schema/base/processPool.json" + "resources/content/schema/base/processPool.json", + "resources/content/schema/base/aiCatalogMetadataView.json", + "resources/content/schema/base/aiCatalogStackLaunchOptions.json", + "resources/content/schema/base/aiCatalogStackLaunchPlan.json", + "resources/content/schema/base/aiCatalogStackLaunchInputs.json" + ], + "addedTuples": [ + [ + "aiCatalogMetadataView", + "collection", + "POST", + "", + "", + "read" + ], + [ + "aiCatalogStackLaunchOptions", + "collection", + "POST", + "", + "", + "read" + ], + [ + "aiCatalogStackLaunchPlan", + "collection", + "GET", + "", + "", + "read" + ], + [ + "aiCatalogStackLaunchPlan", + "collection", + "POST", + "", + "", + "create" + ], + [ + "aiCatalogStackLaunchPlan", + "resource", + "GET", + "", + "", + "read" + ], + [ + "aiCatalogStackLaunchPlan", + "resource", + "POST", + "apply", + "", + "create" + ], + [ + "aiCatalogStackLaunchPlan", + "resource", + "POST", + "cancel", + "", + "ai-catalog-launch:cancel" + ], + [ + "aiCatalogStackLaunchPlan", + "resource", + "POST", + "completeInputs", + "", + "ai-catalog-launch:completeInputs" + ], + [ + "aiCatalogStackLaunchPlan", + "resource", + "POST", + "confirm", + "", + "ai-catalog-launch:confirm" + ] + ], + "changedTuples": [ + { + "before": [ + "service", + "resource", + "POST", + "setservicelinks", + "", + "action:setservicelinks" + ], + "after": [ + "service", + "resource", + "POST", + "setservicelinks", + "", + "update" + ], + "rationale": "Only the existing Service.setservicelinks owner is update. The typed launch preflights original live destination update and each delegated exact action; create does not imply update. Unknown plugin roots remain denied." + } ], - "addedTuples": [], - "changedTuples": [], "authorizationRationale": { - "managedLifecycle": "Closed engine-captured scheduling edges preserve exact managed retirement ancestry while live owner/Key/revision/explicit-DENY remains authoritative; ordinary ancestry is not broadened and named/file storage does not inherit destructive removal.", - "nativeNameSearch": "Closed native name conditions narrow the already-authorized owner query before its bounded page; literal query and cursor/parent restrictions are retained. Memory projections filter before taking a page." + "aiCatalogStackLaunchOptions": "Read-only fixed owner projection; no create grant or secret defaults.", + "aiCatalogStackLaunchPlan": "Dedicated durable plan. Preview/confirm/apply recheck original live destination read/create/update and references; completeInputs/confirm/cancel are verified Cookie-only, including for GENERAL FULL Keys. Apply claims once and normal Stack/Compose owners execute an exact per-event graph, with per-request actor/Key/source revalidation; private answers and proof never enter public DTO or audit payload.", + "serviceSetServiceLinks": "Exact Service action classified update; role schema, original live Key target scope and explicit DENY still apply. No plugin or create-to-update grant.", + "privateOwnerChannel": "Public Catalog/raw proxy initial and redirect targets reject canonical v1-catalog/ai namespace before body/upstream; fixed typed owner loopback calls retain their independent live authorization.", + "aiCatalogMetadataView": "Fixed metadata read POST. Fresh active owner/current-project membership plus live Key PLATFORM catalogTemplate read precede a fixed loopback Catalog projection. No raw proxy/accounts grant, project ancestry inference, forwarded credentials or new JWT. Fine-grained selectors fail closed; template/version logical identities are not cache row IDs." }, "sourceInputChanges": [ + { + "path": "code/framework/api/src/main/java/io/cattle/platform/api/auth/ApiAuditPayload.java", + "before": null, + "after": "697bb6f57b26354f336e14f905bc2a87f8a41acfdf725500652100e90d4e4381" + }, + { + "path": "code/framework/api/src/main/java/io/cattle/platform/api/auth/ApiCookieAuthentication.java", + "before": null, + "after": "b49fe3b141ac1689e49a583bab05caf7a449dc2b3495b0ba391534bc5812d3c4" + }, + { + "path": "code/framework/api/src/main/java/io/cattle/platform/api/auth/CatalogLaunchTransformAuthorization.java", + "before": null, + "after": "b104bb0aed1ae18dc7485aa1f7c7eddf3b6eb9176b7e7209cb2b89534600e4c6" + }, + { + "path": "code/framework/auditing/src/main/java/io/cattle/platform/iaas/api/auditing/AuditServiceImpl.java", + "before": null, + "after": "1f834204996aabfd6e6d3d5bb520d35b80547c5e77b8edea8f25d8d6010cfd4e" + }, + { + "path": "code/framework/eventing/src/main/java/io/cattle/platform/eventing/model/EventDiagnostics.java", + "before": null, + "after": "affeccbf8445e1d61b525df683504de7c084642a52cec8e6fb9371ca935c3034" + }, + { + "path": "code/iaas/api-logic/src/main/java/io/cattle/platform/iaas/api/request/handler/GenericWhitelistedProxy.java", + "before": null, + "after": "9606a7e0f76cb4c7eba033afc897d6d9e5d61045262d582ee94604169817608a" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchAccess.java", + "before": null, + "after": "639ceb2151b6668af77ff2f71ead2cd7699d76d45c17521e46a90af624286b52" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchBinding.java", + "before": null, + "after": "9f75784fa67b7341439d3ffecf8bada16ef0e55a7db3bbb41d6eceed4db90e8d" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchDelegation.java", + "before": null, + "after": "e75f911701471e63f85b70df645040a4142704f8da94f3008ed2187c43b35a1d" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchGateway.java", + "before": null, + "after": "9a12293de31831d7dda5f2e787b809351c347bf95e7b95f6798bb7e18d5ae12c" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchGraph.java", + "before": null, + "after": "26618418c19bd7eef3dc7e5e4cd526072f3a614535a04b914e0559a20f12d875" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchInput.java", + "before": null, + "after": "3db05d510e3e057ae5d10340e0e313111de0a5a7e5558a477e91395f1f4280de" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchMaterializer.java", + "before": null, + "after": "00945aae0ccd8091f6835168bd0d0ff7615be2f00cc86c27f48218520d680f50" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchObservation.java", + "before": null, + "after": "e3ecb29c1585002c61a4c3a6e14e94868c4e9de6da94e5098eb5d2f14b93d82d" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchOptionsResourceManager.java", + "before": null, + "after": "fb2977ff6cbd4819f5ecaa75afdcd5c3d9a3c43add3b5c2d4614379349e74552" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchOptionsService.java", + "before": null, + "after": "318bb0e18d8a7292ff57a0b281d53eb5040e7c4a5fef388baea4aac4acf30d5d" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchOptionsStore.java", + "before": null, + "after": "b4dbbfffcb333ce11c559e10eee78ce2ae9dc1fa5d4a958c475f5a893b270c2b" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPlanResourceManager.java", + "before": null, + "after": "ef70bb6e029fdb446358ad81e9f791f14e892c28bda754b8ce479077fb85ff98" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPlanService.java", + "before": null, + "after": "77b8f8b2b4ade110064ba0a874db04c1d5adbfe9df68655b8760c395270a05e3" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPlanStore.java", + "before": null, + "after": "8716e8f4038bad48098f16c9009446c4e77f379cba50d3049897aa2442fd7b22" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPrivate.java", + "before": null, + "after": "df91328e28fca5f15aceda4faaf57be47c8165dfc5cbf36894abd12935c8d3b2" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchResponseFilter.java", + "before": null, + "after": "0e35935d8e3ce19a843d3770b9a574b0c2d501612a8f6211f077834f7975bb60" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchRunner.java", + "before": null, + "after": "e6e530a39cc6ca2d270038f0084ed6c104f45d69ebfe7a307391e90918c0f6c9" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyAuthorizationService.java", + "before": "9ceda0f5118d38fc45fc83bd4a16eb92717a20f7837bcabb804975600c59d2c5", + "after": "d3cac29f7b6f61be0bda38f643115d08877d59e99b9312575f064290e73ede27" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyOperations.java", + "before": "494a57d48564da85f14de564a82906444fa732f1adb201fe27d8c0ca88ea65e5", + "after": "28847a8d6873d8e8fe1644a19813e8f8f9d1917a5c1b369dab8abcb882e6a9b6" + }, { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", - "before": "fcd8d3724c1a37b2b77cab3e60ee3e973b349462833c1bf0bcc8f099d6f3567c", - "after": "645652a1352b74cf6ad4c2b1a9bbdfee1d168cef9df7c59e459d84c17d547c17" + "before": "645652a1352b74cf6ad4c2b1a9bbdfee1d168cef9df7c59e459d84c17d547c17", + "after": "95e9c38861b984e995770e5ddf6d7af21c96d1bff1d8848d1ad2e3a54722efd2" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/impl/ApiAuthenticator.java", + "before": "7a3e331dc9e23ae1689495b6ce4066a9decb8293def66fbffa6e0e404697db12", + "after": "d412d32cf7032b4bb0dde546a9e22193fc29ecae71b5c1efcbb052bd4590945d" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/integration/internal/rancher/TokenAuthLookup.java", + "before": null, + "after": "11c66db998415be5deab8a34df362dcb299a7b1a8df938ef1afb6f6602b71c91" + }, + { + "path": "code/iaas/logic-common/src/main/java/io/cattle/platform/process/common/handler/EventBasedProcessHandler.java", + "before": null, + "after": "d784906d3bd0e0399dc38cd38ddc5ee38c49850e7a51ea07d2a4a158dcb068de" + }, + { + "path": "code/iaas/logic-common/src/main/java/io/cattle/platform/process/common/handler/ProcessEventDecorator.java", + "before": null, + "after": "b0dc3d894c3ae0345e374cda8af588ac2e6c17c74f25501e6689a28d4ef934e5" + }, + { + "path": "code/iaas/service-discovery/api/src/main/java/io/cattle/platform/servicediscovery/api/filter/ArchiveValidationFilter.java", + "before": "63fbdcc3d0ac73186b181afc55d0e0aae4424a347a367724348802246cad823c", + "after": "908e6e0bf0d665d2392481f6d6e59d27c3cd89b4b35471fe587d6ed14e591890" + }, + { + "path": "code/implementation/docker/api/src/main/java/io/cattle/platform/docker/api/transform/TransformInspect.java", + "before": null, + "after": "c67974b0abbb3b7c7801b51ca95a649e95e0853fba9c1500da6b4b5977a0afb2" + }, + { + "path": "code/packaging/app-config/src/main/java/io/cattle/platform/app/IaasApiConfig.java", + "before": null, + "after": "02184dc6ae781547e850c80cf51ddb4f33cbc7b2f799aba3ca1e59c8eb9cf34f" + }, + { + "path": "resources/content/schema/admin/admin-auth.json", + "before": "79a757118dd66055c6e7e4c03ded4b0dd8ef1965887c50a4c106e15836d4938f", + "after": "6ea49e1130a2b9218e6c060038c73c89be5b9e05b039d3a0b81475e892d21504" + }, + { + "path": "resources/content/schema/base/aiCatalogMetadataView.json", + "before": null, + "after": "5581897314b1cfe9135783fb8846db50ff6f9d62289b5ab35e60ab7ca8b36515" + }, + { + "path": "resources/content/schema/base/aiCatalogStackLaunchInputs.json", + "before": null, + "after": "05aa9a7b459a82efcf0331b3d6c8262e1b5c879643aef6384c67e3a12980bf4c" + }, + { + "path": "resources/content/schema/base/aiCatalogStackLaunchOptions.json", + "before": null, + "after": "30137b75ac50b6b04adec688ca56359fd7d49843f8342c423a906b998da5c12a" + }, + { + "path": "resources/content/schema/base/aiCatalogStackLaunchPlan.json", + "before": null, + "after": "5886387a8b25893d4afc5bb127dd8305646748e08a86b65002d8e0d8e05b328d" + }, + { + "path": "resources/content/schema/base/aiResourceChangePlan.json", + "before": "ec4b5ceb31e42dceb71c2fb0f475daf868a19a08ad9644dcf17ee8c06c769786", + "after": "21b4acfd55e2aa64b725bacd520655daf7f707141e4226343c16a5b6fae47d8c" + }, + { + "path": "resources/content/schema/project/project-auth.json", + "before": "96dcb3b12d6ba0a15e5532df71c68683b2fe87a8946ecb71c10109dea4f17585", + "after": "a924ebe3e6ea7a39374d7d162fd020807cb94900c849c82d286df121db27ee6c" + }, + { + "path": "resources/content/schema/user/user-auth.json", + "before": "91c44ff87f288c967d38cfe0c6c1dd04e4ac09919cd6c6ba8407806a61168a2f", + "after": "0f977be3a4e6718753ba8a248e73f1014886afbee1d5387249e762b4146b7b73" } ] }, @@ -628,315 +956,229 @@ "resources/content/schema/base/aiCatalogMetadataView.json", "resources/content/schema/base/aiCatalogStackLaunchOptions.json", "resources/content/schema/base/aiCatalogStackLaunchPlan.json", - "resources/content/schema/base/aiCatalogStackLaunchInputs.json" + "resources/content/schema/base/aiCatalogStackLaunchInputs.json", + "resources/content/schema/base/aiAuditQuery.json", + "resources/content/schema/base/aiAuditSourcePageInput.json" ], "addedTuples": [ [ - "aiCatalogMetadataView", - "collection", - "POST", - "", - "", - "read" - ], - [ - "aiCatalogStackLaunchOptions", + "aiAuditQuery", "collection", "POST", "", "", "read" - ], - [ - "aiCatalogStackLaunchPlan", - "collection", - "GET", - "", - "", - "read" - ], - [ - "aiCatalogStackLaunchPlan", - "collection", - "POST", - "", - "", - "create" - ], - [ - "aiCatalogStackLaunchPlan", - "resource", - "GET", - "", - "", - "read" - ], - [ - "aiCatalogStackLaunchPlan", - "resource", - "POST", - "apply", - "", - "create" - ], - [ - "aiCatalogStackLaunchPlan", - "resource", - "POST", - "cancel", - "", - "ai-catalog-launch:cancel" - ], - [ - "aiCatalogStackLaunchPlan", - "resource", - "POST", - "completeInputs", - "", - "ai-catalog-launch:completeInputs" - ], - [ - "aiCatalogStackLaunchPlan", - "resource", - "POST", - "confirm", - "", - "ai-catalog-launch:confirm" ] ], "changedTuples": [ - { - "before": [ - "service", + [ + [ + "dnsService", "resource", "POST", "setservicelinks", "", "action:setservicelinks" ], - "after": [ - "service", + [ + "dnsService", "resource", "POST", "setservicelinks", "", "update" - ], - "rationale": "Only the existing Service.setservicelinks owner is update. The typed launch preflights original live destination update and each delegated exact action; create does not imply update. Unknown plugin roots remain denied." - } + ] + ] ], "authorizationRationale": { - "aiCatalogStackLaunchOptions": "Read-only fixed owner projection; no create grant or secret defaults.", - "aiCatalogStackLaunchPlan": "Dedicated durable plan. Preview/confirm/apply recheck original live destination read/create/update and references; completeInputs/confirm/cancel are verified Cookie-only, including for GENERAL FULL Keys. Apply claims once and normal Stack/Compose owners execute an exact per-event graph, with per-request actor/Key/source revalidation; private answers and proof never enter public DTO or audit payload.", - "serviceSetServiceLinks": "Exact Service action classified update; role schema, original live Key target scope and explicit DENY still apply. No plugin or create-to-update grant.", - "privateOwnerChannel": "Public Catalog/raw proxy initial and redirect targets reject canonical v1-catalog/ai namespace before body/upstream; fixed typed owner loopback calls retain their independent live authorization.", - "aiCatalogMetadataView": "Fixed metadata read POST. Fresh active owner/current-project membership plus live Key PLATFORM catalogTemplate read precede a fixed loopback Catalog projection. No raw proxy/accounts grant, project ancestry inference, forwarded credentials or new JWT. Fine-grained selectors fail closed; template/version logical identities are not cache row IDs." + "aiAuditQuery": "Read-semantic metadata admission only. Original native role/schema/current Key and SQL/row filters authorize each source page. Fixed installed broker read-only CLI aggregates using private original credentials; Engine observes complete owner output and persists canonical ALLOW/DENY/error through existing ApiKeyAuditSink. No client-reported result is authoritative.", + "aiAuditSourcePages": "Exactly project/account/apiKey/auditLog with bounded typed ID/time/page input; no independent input route. Original account/project selection, current membership and each native GET apply. Restricted Keys cannot mutate/export credentials; target-Key query requires original actual Key metadata read. Every Key source page pins revision; native API direct/raw routes retain their prior purpose guard and Full/legacy behavior." }, "sourceInputChanges": [ { "path": "code/framework/api/src/main/java/io/cattle/platform/api/auth/ApiAuditPayload.java", - "before": null, - "after": "697bb6f57b26354f336e14f905bc2a87f8a41acfdf725500652100e90d4e4381" + "before": "697bb6f57b26354f336e14f905bc2a87f8a41acfdf725500652100e90d4e4381", + "after": "16122e192f490b7866d3b0af3ed4981184c938d8446ec9b7d4c892d68cf2d67d" }, { - "path": "code/framework/api/src/main/java/io/cattle/platform/api/auth/ApiCookieAuthentication.java", + "path": "code/framework/api/src/main/java/io/cattle/platform/api/auth/ApiKeyAuditSink.java", "before": null, - "after": "b49fe3b141ac1689e49a583bab05caf7a449dc2b3495b0ba391534bc5812d3c4" + "after": "c04eec56c774f68254c832cc8916b57ec000d5fce3bd07e5cafb65260a48fe9b" }, { - "path": "code/framework/api/src/main/java/io/cattle/platform/api/auth/CatalogLaunchTransformAuthorization.java", + "path": "code/framework/auditing/src/main/java/io/cattle/platform/iaas/api/auditing/AuditLogOutPutFilter.java", "before": null, - "after": "b104bb0aed1ae18dc7485aa1f7c7eddf3b6eb9176b7e7209cb2b89534600e4c6" + "after": "368c21b043bdfc149f3d5a8663cf12b6ad93f0efdec0df6b7e065d62200f4ac7" }, { "path": "code/framework/auditing/src/main/java/io/cattle/platform/iaas/api/auditing/AuditServiceImpl.java", - "before": null, - "after": "1f834204996aabfd6e6d3d5bb520d35b80547c5e77b8edea8f25d8d6010cfd4e" + "before": "1f834204996aabfd6e6d3d5bb520d35b80547c5e77b8edea8f25d8d6010cfd4e", + "after": "a10a5d8e7ca754601ea2c5a876c318069b6639c073e616d283ae71694bc95179" }, { - "path": "code/framework/eventing/src/main/java/io/cattle/platform/eventing/model/EventDiagnostics.java", + "path": "code/framework/engine/src/main/java/io/cattle/platform/engine/process/ProcessAuthorization.java", "before": null, - "after": "affeccbf8445e1d61b525df683504de7c084642a52cec8e6fb9371ca935c3034" + "after": "a717b03de1ec528f7047161679be436535d68fb416b573c3aaf5b09a2e44b520" }, { - "path": "code/iaas/api-logic/src/main/java/io/cattle/platform/iaas/api/request/handler/GenericWhitelistedProxy.java", - "before": null, - "after": "9606a7e0f76cb4c7eba033afc897d6d9e5d61045262d582ee94604169817608a" + "path": "code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/request/resource/ResourceManager.java", + "before": "8f5f72c17541e73cab9f59ad8d36c06593baef517628a923967bc4c18f82b999", + "after": "ef08c305584fe79e2218d360dbc2ce6f3b29b64f4123ac325c8473430bc0a1f1" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchAccess.java", - "before": null, - "after": "639ceb2151b6668af77ff2f71ead2cd7699d76d45c17521e46a90af624286b52" + "path": "code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/request/resource/impl/FilteredResourceManager.java", + "before": "a140040f0be95fd7872eb7f7e78f5824329725a109d7bc0c79d960dbc0709e77", + "after": "d2c6a28809df4912b2b22ce22e9f4e48304b91c993144867d05fa5d65f07ae76" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchBinding.java", + "path": "code/framework/schema/src/main/java/io/cattle/platform/schema/processor/NotWritablePostProcessor.java", "before": null, - "after": "9f75784fa67b7341439d3ffecf8bada16ef0e55a7db3bbb41d6eceed4db90e8d" + "after": "c42a2b1aea75d4daae5671c702e3242c9cd1e7d32e7a5280fc3a0f6415ca829a" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchDelegation.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQuery.java", "before": null, - "after": "e75f911701471e63f85b70df645040a4142704f8da94f3008ed2187c43b35a1d" + "after": "6ef0559fdec19c2fe76742587dd5b5c88b5ec904ee3544f70dd6937fffe1e455" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchGateway.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQueryResourceManager.java", "before": null, - "after": "9a12293de31831d7dda5f2e787b809351c347bf95e7b95f6798bb7e18d5ae12c" + "after": "bdeaebe2fbc3f84be1c9bc19b0bcc7d534a5d43888cc3a95ec446d300458c8c2" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchGraph.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQueryRunner.java", "before": null, - "after": "26618418c19bd7eef3dc7e5e4cd526072f3a614535a04b914e0559a20f12d875" + "after": "608fa5f5b412dccdf154290094ff1d67204c092cfb60b850d8d7a3124f53c812" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchInput.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQueryService.java", "before": null, - "after": "3db05d510e3e057ae5d10340e0e313111de0a5a7e5558a477e91395f1f4280de" + "after": "4067cc8685399b2b2bfb9e7b5eaddd10b906f63fccf286ef7e118622e4e80ea6" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchMaterializer.java", - "before": null, - "after": "00945aae0ccd8091f6835168bd0d0ff7615be2f00cc86c27f48218520d680f50" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchResponseFilter.java", + "before": "0e35935d8e3ce19a843d3770b9a574b0c2d501612a8f6211f077834f7975bb60", + "after": "9884cc5bc272d0a872ab7b48f5365863dfc8154b0e6c291fe418bdc14541be73" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchObservation.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiAuditSourcePage.java", "before": null, - "after": "e3ecb29c1585002c61a4c3a6e14e94868c4e9de6da94e5098eb5d2f14b93d82d" + "after": "4e47ab9f1fef9108e68a0471b633d3d99f5f5069591e7dcecfe57018f09b6b78" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchOptionsResourceManager.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiAuditSourcePageInput.java", "before": null, - "after": "fb2977ff6cbd4819f5ecaa75afdcd5c3d9a3c43add3b5c2d4614379349e74552" + "after": "771bdb99ca900a268c900c957d476f3f8d96b31ce45d56583e7c572f3abe73c5" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchOptionsService.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiResourceViewResourceManager.java", "before": null, - "after": "318bb0e18d8a7292ff57a0b281d53eb5040e7c4a5fef388baea4aac4acf30d5d" + "after": "ea08a26aee7cfa32df3485dd9c4e2e7bd63ca5d2e680cdbabdfcdc5f3c63b8dd" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchOptionsStore.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiResourceViewService.java", "before": null, - "after": "b4dbbfffcb333ce11c559e10eee78ce2ae9dc1fa5d4a958c475f5a893b270c2b" + "after": "54f9aeaeecbf135e34210417f5cf7ec128a90e05b1971fc351ed4bdd76bf8585" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPlanResourceManager.java", - "before": null, - "after": "ef70bb6e029fdb446358ad81e9f791f14e892c28bda754b8ce479077fb85ff98" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyAuthorizationService.java", + "before": "d3cac29f7b6f61be0bda38f643115d08877d59e99b9312575f064290e73ede27", + "after": "85a065246a8f40e1d9a64d984f49368d488e5d9b712029b5e3e306ca37aeab47" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPlanService.java", - "before": null, - "after": "77b8f8b2b4ade110064ba0a874db04c1d5adbfe9df68655b8760c395270a05e3" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyOperations.java", + "before": "28847a8d6873d8e8fe1644a19813e8f8f9d1917a5c1b369dab8abcb882e6a9b6", + "after": "662bbef806ecf3b266699bb00809fe62b712c9610b36788cfb76e244de37940a" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPlanStore.java", - "before": null, - "after": "8716e8f4038bad48098f16c9009446c4e77f379cba50d3049897aa2442fd7b22" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyProcessAuthorization.java", + "before": "65052468195ad36213f68dc585d63d1cebc13409f7a92704d53297e2efcb482e", + "after": "1bf968d28d977725fa426fe7f32b00d5bc322979c0bfe1e0501fc2c34c03100e" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPrivate.java", - "before": null, - "after": "df91328e28fca5f15aceda4faaf57be47c8165dfc5cbf36894abd12935c8d3b2" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", + "before": "95e9c38861b984e995770e5ddf6d7af21c96d1bff1d8848d1ad2e3a54722efd2", + "after": "3c299d683055c0301f93b4bc8d23252215d1d9c0746d0aaafa0b52447d3eb26b" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchResponseFilter.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiAliasServiceChange.java", "before": null, - "after": "0e35935d8e3ce19a843d3770b9a574b0c2d501612a8f6211f077834f7975bb60" + "after": "fa69385c6ffee09261466e995e59474b632302225088729de3242ccaf2b2118b" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchRunner.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiExternalServiceChange.java", "before": null, - "after": "e6e530a39cc6ca2d270038f0084ed6c104f45d69ebfe7a307391e90918c0f6c9" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyAuthorizationService.java", - "before": "9ceda0f5118d38fc45fc83bd4a16eb92717a20f7837bcabb804975600c59d2c5", - "after": "d3cac29f7b6f61be0bda38f643115d08877d59e99b9312575f064290e73ede27" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyOperations.java", - "before": "494a57d48564da85f14de564a82906444fa732f1adb201fe27d8c0ca88ea65e5", - "after": "28847a8d6873d8e8fe1644a19813e8f8f9d1917a5c1b369dab8abcb882e6a9b6" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", - "before": "645652a1352b74cf6ad4c2b1a9bbdfee1d168cef9df7c59e459d84c17d547c17", - "after": "95e9c38861b984e995770e5ddf6d7af21c96d1bff1d8848d1ad2e3a54722efd2" + "after": "d9497a9c37842c09e833d434e5f361585f721a72eff9976c5b66902181f392e5" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/impl/ApiAuthenticator.java", - "before": "7a3e331dc9e23ae1689495b6ce4066a9decb8293def66fbffa6e0e404697db12", - "after": "d412d32cf7032b4bb0dde546a9e22193fc29ecae71b5c1efcbb052bd4590945d" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDescriptor.java", + "before": null, + "after": "2ef7555c7864a2ce91a7c28951e895da412f68849b6cc3ec04350a75b35186f8" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/integration/internal/rancher/TokenAuthLookup.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDomain.java", "before": null, - "after": "11c66db998415be5deab8a34df362dcb299a7b1a8df938ef1afb6f6602b71c91" + "after": "aafe0ea7a5f60f7e9dc926067318cb2d470ec066cc1e5986b76b2c79122570a4" }, { - "path": "code/iaas/logic-common/src/main/java/io/cattle/platform/process/common/handler/EventBasedProcessHandler.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanService.java", "before": null, - "after": "d784906d3bd0e0399dc38cd38ddc5ee38c49850e7a51ea07d2a4a158dcb068de" + "after": "d0605f3e94757996e699e4083b1cd314d6d68acf623358a92f9841bc75384fb9" }, { - "path": "code/iaas/logic-common/src/main/java/io/cattle/platform/process/common/handler/ProcessEventDecorator.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanStore.java", "before": null, - "after": "b0dc3d894c3ae0345e374cda8af588ac2e6c17c74f25501e6689a28d4ef934e5" + "after": "9862ed000b4b40a6a7643968313c250fad9b1e718a684dccbab8f35c3a29cd5f" }, { - "path": "code/iaas/service-discovery/api/src/main/java/io/cattle/platform/servicediscovery/api/filter/ArchiveValidationFilter.java", - "before": "63fbdcc3d0ac73186b181afc55d0e0aae4424a347a367724348802246cad823c", - "after": "908e6e0bf0d665d2392481f6d6e59d27c3cd89b4b35471fe587d6ed14e591890" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeProcessObserver.java", + "before": null, + "after": "6f7898590bb64e55cb815c9b1a51f4ce00540a6268e8fa4914ef1b6b445f5a70" }, { - "path": "code/implementation/docker/api/src/main/java/io/cattle/platform/docker/api/transform/TransformInspect.java", + "path": "code/iaas/service-discovery/server/src/main/java/io/cattle/platform/servicediscovery/dao/impl/ServiceConsumeMapDaoImpl.java", "before": null, - "after": "c67974b0abbb3b7c7801b51ca95a649e95e0853fba9c1500da6b4b5977a0afb2" + "after": "a127711511a3f1271d441235f9889d63e06a5c2d457974e4a45bd04f1e7e5747" }, { "path": "code/packaging/app-config/src/main/java/io/cattle/platform/app/IaasApiConfig.java", - "before": null, - "after": "02184dc6ae781547e850c80cf51ddb4f33cbc7b2f799aba3ca1e59c8eb9cf34f" + "before": "02184dc6ae781547e850c80cf51ddb4f33cbc7b2f799aba3ca1e59c8eb9cf34f", + "after": "59b633a3f6614f811b5f14b0eeeeb1f99683d319a2c28bea2093f48a33a53130" }, { "path": "resources/content/schema/admin/admin-auth.json", - "before": "79a757118dd66055c6e7e4c03ded4b0dd8ef1965887c50a4c106e15836d4938f", - "after": "6ea49e1130a2b9218e6c060038c73c89be5b9e05b039d3a0b81475e892d21504" - }, - { - "path": "resources/content/schema/base/aiCatalogMetadataView.json", - "before": null, - "after": "5581897314b1cfe9135783fb8846db50ff6f9d62289b5ab35e60ab7ca8b36515" + "before": "6ea49e1130a2b9218e6c060038c73c89be5b9e05b039d3a0b81475e892d21504", + "after": "27630fdb4d5cf7a1dcd7e693b84d0b31513d627a64a5d2365119075aca6d4f85" }, { - "path": "resources/content/schema/base/aiCatalogStackLaunchInputs.json", + "path": "resources/content/schema/base/aiAuditQuery.json", "before": null, - "after": "05aa9a7b459a82efcf0331b3d6c8262e1b5c879643aef6384c67e3a12980bf4c" + "after": "c12e694997a08c3e9849413f45b96d7d9cf2471289d35be54a60903d22e609eb" }, { - "path": "resources/content/schema/base/aiCatalogStackLaunchOptions.json", + "path": "resources/content/schema/base/aiAuditSourcePageInput.json", "before": null, - "after": "30137b75ac50b6b04adec688ca56359fd7d49843f8342c423a906b998da5c12a" + "after": "2aca5cba9323daae33a7171ac5f3bec2591cbdbffbdc32cf263ac8398a75e444" }, { - "path": "resources/content/schema/base/aiCatalogStackLaunchPlan.json", - "before": null, - "after": "5886387a8b25893d4afc5bb127dd8305646748e08a86b65002d8e0d8e05b328d" + "path": "resources/content/schema/base/aiResourceChangePlan.json", + "before": "21b4acfd55e2aa64b725bacd520655daf7f707141e4226343c16a5b6fae47d8c", + "after": "90db2324422f25129edf155127da8e29303b74fe2467797d4459b1df451e9439" }, { - "path": "resources/content/schema/base/aiResourceChangePlan.json", - "before": "ec4b5ceb31e42dceb71c2fb0f475daf868a19a08ad9644dcf17ee8c06c769786", - "after": "21b4acfd55e2aa64b725bacd520655daf7f707141e4226343c16a5b6fae47d8c" + "path": "resources/content/schema/base/aiResourceView.json", + "before": "024fb697f3d5e1ed511544ff6922f3b78c351f01e74df1a36faeee3e7f3dba95", + "after": "5bd8e7f91b44165d8f57ebb5b17689c40b2c236d1d6a80af0ade78dba552cc73" }, { "path": "resources/content/schema/project/project-auth.json", - "before": "96dcb3b12d6ba0a15e5532df71c68683b2fe87a8946ecb71c10109dea4f17585", - "after": "a924ebe3e6ea7a39374d7d162fd020807cb94900c849c82d286df121db27ee6c" + "before": "a924ebe3e6ea7a39374d7d162fd020807cb94900c849c82d286df121db27ee6c", + "after": "c752d35a5b2b2bdc65af5914d89071948e5b10e41772736ade7f89dfd2554a59" }, { "path": "resources/content/schema/user/user-auth.json", - "before": "91c44ff87f288c967d38cfe0c6c1dd04e4ac09919cd6c6ba8407806a61168a2f", - "after": "0f977be3a4e6718753ba8a248e73f1014886afbee1d5387249e762b4146b7b73" + "before": "0f977be3a4e6718753ba8a248e73f1014886afbee1d5387249e762b4146b7b73", + "after": "0f96a7e195647b967d4f83cab74d6a0fc5c442a896baa54384937af765bc2d9e" } ] }, @@ -954,225 +1196,60 @@ "resources/content/schema/base/aiAuditQuery.json", "resources/content/schema/base/aiAuditSourcePageInput.json" ], - "addedTuples": [ - [ - "aiAuditQuery", - "collection", - "POST", - "", - "", - "read" - ] - ], - "changedTuples": [ - [ - [ - "dnsService", - "resource", - "POST", - "setservicelinks", - "", - "action:setservicelinks" - ], - [ - "dnsService", - "resource", - "POST", - "setservicelinks", - "", - "update" - ] - ] - ], + "addedTuples": [], + "changedTuples": [], "authorizationRationale": { - "aiAuditQuery": "Read-semantic metadata admission only. Original native role/schema/current Key and SQL/row filters authorize each source page. Fixed installed broker read-only CLI aggregates using private original credentials; Engine observes complete owner output and persists canonical ALLOW/DENY/error through existing ApiKeyAuditSink. No client-reported result is authoritative.", - "aiAuditSourcePages": "Exactly project/account/apiKey/auditLog with bounded typed ID/time/page input; no independent input route. Original account/project selection, current membership and each native GET apply. Restricted Keys cannot mutate/export credentials; target-Key query requires original actual Key metadata read. Every Key source page pins revision; native API direct/raw routes retain their prior purpose guard and Full/legacy behavior." + "certificate": "Only name/description; current native method/field schema, row lock, safe UUID/public fingerprint CAS, Cookie-human approval and original Key revision remain required. No PEM/key/chain field or raw proxy is admitted.", + "nativeNetworkRemoval": "Actual immutable Java execution frames include native processName. Only Instance DELETE/delete, exact persisted owner/UUID/FK and all IP maps qualify for native nic.remove reentry. Missing/stop frames, foreign/shared/reassigned children and explicit NIC/IP/map/service DENY remain denied. Live paths and Full/legacy retain their original owner behavior.", + "terminalDenial": "Only the structured synchronous child AUTHORIZATION_DENIED terminates its parent. Other exit/retry semantics and durable completion-audit replay are unchanged.", + "auditOwnerTopology": "The fixed private CLI shares the configured broker upstream. Java reconstructs only HTTP(S) loopback origins and bounded ports from its exact nonsecret operator setting after clearing all other environment; credentials stay private stdin. No HTTP or tool-specified URL is accepted.", + "audit": "Existing durable metadata-only decision owner includes the explicitly reviewed certificate/externalService/dnsService domains. It does not authorize their operation or log private material." }, "sourceInputChanges": [ { - "path": "code/framework/api/src/main/java/io/cattle/platform/api/auth/ApiAuditPayload.java", - "before": "697bb6f57b26354f336e14f905bc2a87f8a41acfdf725500652100e90d4e4381", - "after": "16122e192f490b7866d3b0af3ed4981184c938d8446ec9b7d4c892d68cf2d67d" - }, - { - "path": "code/framework/api/src/main/java/io/cattle/platform/api/auth/ApiKeyAuditSink.java", - "before": null, - "after": "c04eec56c774f68254c832cc8916b57ec000d5fce3bd07e5cafb65260a48fe9b" - }, - { - "path": "code/framework/auditing/src/main/java/io/cattle/platform/iaas/api/auditing/AuditLogOutPutFilter.java", - "before": null, - "after": "368c21b043bdfc149f3d5a8663cf12b6ad93f0efdec0df6b7e065d62200f4ac7" - }, - { - "path": "code/framework/auditing/src/main/java/io/cattle/platform/iaas/api/auditing/AuditServiceImpl.java", - "before": "1f834204996aabfd6e6d3d5bb520d35b80547c5e77b8edea8f25d8d6010cfd4e", - "after": "a10a5d8e7ca754601ea2c5a876c318069b6639c073e616d283ae71694bc95179" - }, - { - "path": "code/framework/engine/src/main/java/io/cattle/platform/engine/process/ProcessAuthorization.java", - "before": null, - "after": "a717b03de1ec528f7047161679be436535d68fb416b573c3aaf5b09a2e44b520" - }, - { - "path": "code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/request/resource/ResourceManager.java", - "before": "8f5f72c17541e73cab9f59ad8d36c06593baef517628a923967bc4c18f82b999", - "after": "ef08c305584fe79e2218d360dbc2ce6f3b29b64f4123ac325c8473430bc0a1f1" - }, - { - "path": "code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/request/resource/impl/FilteredResourceManager.java", - "before": "a140040f0be95fd7872eb7f7e78f5824329725a109d7bc0c79d960dbc0709e77", - "after": "d2c6a28809df4912b2b22ce22e9f4e48304b91c993144867d05fa5d65f07ae76" - }, - { - "path": "code/framework/schema/src/main/java/io/cattle/platform/schema/processor/NotWritablePostProcessor.java", - "before": null, - "after": "c42a2b1aea75d4daae5671c702e3242c9cd1e7d32e7a5280fc3a0f6415ca829a" + "path": "code/framework/auditing/src/main/java/io/cattle/platform/iaas/api/auditing/AuditServiceImpl.java", + "before": "a10a5d8e7ca754601ea2c5a876c318069b6639c073e616d283ae71694bc95179", + "after": "cb6bb0a8ed3dda48bedd3ae89ed78a490f644c1040c5aa16463e1e701250988e" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQuery.java", + "path": "code/framework/engine/src/main/java/io/cattle/platform/engine/context/EngineContext.java", "before": null, - "after": "6ef0559fdec19c2fe76742587dd5b5c88b5ec904ee3544f70dd6937fffe1e455" + "after": "ba91b4da42d1f2ea5a2b9709818c2a8f4b967c2c730d5681b53d9dbe94ce8968" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQueryResourceManager.java", + "path": "code/framework/engine/src/main/java/io/cattle/platform/engine/process/impl/DefaultProcessInstanceImpl.java", "before": null, - "after": "bdeaebe2fbc3f84be1c9bc19b0bcc7d534a5d43888cc3a95ec446d300458c8c2" + "after": "986e14156ce42ac72033fad21289db4e3732469378cb6c9b0ae1d0a4c36376b0" }, { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQueryRunner.java", - "before": null, - "after": "608fa5f5b412dccdf154290094ff1d67204c092cfb60b850d8d7a3124f53c812" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQueryService.java", - "before": null, - "after": "4067cc8685399b2b2bfb9e7b5eaddd10b906f63fccf286ef7e118622e4e80ea6" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchResponseFilter.java", - "before": "0e35935d8e3ce19a843d3770b9a574b0c2d501612a8f6211f077834f7975bb60", - "after": "9884cc5bc272d0a872ab7b48f5365863dfc8154b0e6c291fe418bdc14541be73" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiAuditSourcePage.java", - "before": null, - "after": "4e47ab9f1fef9108e68a0471b633d3d99f5f5069591e7dcecfe57018f09b6b78" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiAuditSourcePageInput.java", - "before": null, - "after": "771bdb99ca900a268c900c957d476f3f8d96b31ce45d56583e7c572f3abe73c5" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiResourceViewResourceManager.java", - "before": null, - "after": "ea08a26aee7cfa32df3485dd9c4e2e7bd63ca5d2e680cdbabdfcdc5f3c63b8dd" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiResourceViewService.java", - "before": null, - "after": "54f9aeaeecbf135e34210417f5cf7ec128a90e05b1971fc351ed4bdd76bf8585" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyAuthorizationService.java", - "before": "d3cac29f7b6f61be0bda38f643115d08877d59e99b9312575f064290e73ede27", - "after": "85a065246a8f40e1d9a64d984f49368d488e5d9b712029b5e3e306ca37aeab47" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyOperations.java", - "before": "28847a8d6873d8e8fe1644a19813e8f8f9d1917a5c1b369dab8abcb882e6a9b6", - "after": "662bbef806ecf3b266699bb00809fe62b712c9610b36788cfb76e244de37940a" + "before": "608fa5f5b412dccdf154290094ff1d67204c092cfb60b850d8d7a3124f53c812", + "after": "684fa84a259118a13d5a1ef20f76e05592ef867492e3fc54c1dcb94c06bb5758" }, { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyProcessAuthorization.java", - "before": "65052468195ad36213f68dc585d63d1cebc13409f7a92704d53297e2efcb482e", - "after": "1bf968d28d977725fa426fe7f32b00d5bc322979c0bfe1e0501fc2c34c03100e" + "before": "1bf968d28d977725fa426fe7f32b00d5bc322979c0bfe1e0501fc2c34c03100e", + "after": "39ac76abfff5b7a8d95f722f72a4869443ec9c4e99cac754b2690f7ab5be382d" }, { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", - "before": "95e9c38861b984e995770e5ddf6d7af21c96d1bff1d8848d1ad2e3a54722efd2", - "after": "3c299d683055c0301f93b4bc8d23252215d1d9c0746d0aaafa0b52447d3eb26b" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiAliasServiceChange.java", - "before": null, - "after": "fa69385c6ffee09261466e995e59474b632302225088729de3242ccaf2b2118b" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiExternalServiceChange.java", - "before": null, - "after": "d9497a9c37842c09e833d434e5f361585f721a72eff9976c5b66902181f392e5" + "before": "3c299d683055c0301f93b4bc8d23252215d1d9c0746d0aaafa0b52447d3eb26b", + "after": "e755cdf32b48df5392cc6700e0d86890393828da25f957cdfc60c9e6ce157968" }, { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDescriptor.java", - "before": null, - "after": "2ef7555c7864a2ce91a7c28951e895da412f68849b6cc3ec04350a75b35186f8" + "before": "2ef7555c7864a2ce91a7c28951e895da412f68849b6cc3ec04350a75b35186f8", + "after": "542f4d8b53b7360a4b72570466f63f027469d5bf2f0e3ce66ea3d6b6ceb6f417" }, { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDomain.java", - "before": null, - "after": "aafe0ea7a5f60f7e9dc926067318cb2d470ec066cc1e5986b76b2c79122570a4" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanService.java", - "before": null, - "after": "d0605f3e94757996e699e4083b1cd314d6d68acf623358a92f9841bc75384fb9" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanStore.java", - "before": null, - "after": "9862ed000b4b40a6a7643968313c250fad9b1e718a684dccbab8f35c3a29cd5f" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeProcessObserver.java", - "before": null, - "after": "6f7898590bb64e55cb815c9b1a51f4ce00540a6268e8fa4914ef1b6b445f5a70" - }, - { - "path": "code/iaas/service-discovery/server/src/main/java/io/cattle/platform/servicediscovery/dao/impl/ServiceConsumeMapDaoImpl.java", - "before": null, - "after": "a127711511a3f1271d441235f9889d63e06a5c2d457974e4a45bd04f1e7e5747" - }, - { - "path": "code/packaging/app-config/src/main/java/io/cattle/platform/app/IaasApiConfig.java", - "before": "02184dc6ae781547e850c80cf51ddb4f33cbc7b2f799aba3ca1e59c8eb9cf34f", - "after": "59b633a3f6614f811b5f14b0eeeeb1f99683d319a2c28bea2093f48a33a53130" - }, - { - "path": "resources/content/schema/admin/admin-auth.json", - "before": "6ea49e1130a2b9218e6c060038c73c89be5b9e05b039d3a0b81475e892d21504", - "after": "27630fdb4d5cf7a1dcd7e693b84d0b31513d627a64a5d2365119075aca6d4f85" - }, - { - "path": "resources/content/schema/base/aiAuditQuery.json", - "before": null, - "after": "c12e694997a08c3e9849413f45b96d7d9cf2471289d35be54a60903d22e609eb" - }, - { - "path": "resources/content/schema/base/aiAuditSourcePageInput.json", - "before": null, - "after": "2aca5cba9323daae33a7171ac5f3bec2591cbdbffbdc32cf263ac8398a75e444" + "before": "aafe0ea7a5f60f7e9dc926067318cb2d470ec066cc1e5986b76b2c79122570a4", + "after": "2fc7645b2ce573ae02ebc2ec7e20548dda2e0a738d8e65d056650a6c85883c3e" }, { "path": "resources/content/schema/base/aiResourceChangePlan.json", - "before": "21b4acfd55e2aa64b725bacd520655daf7f707141e4226343c16a5b6fae47d8c", - "after": "90db2324422f25129edf155127da8e29303b74fe2467797d4459b1df451e9439" - }, - { - "path": "resources/content/schema/base/aiResourceView.json", - "before": "024fb697f3d5e1ed511544ff6922f3b78c351f01e74df1a36faeee3e7f3dba95", - "after": "5bd8e7f91b44165d8f57ebb5b17689c40b2c236d1d6a80af0ade78dba552cc73" - }, - { - "path": "resources/content/schema/project/project-auth.json", - "before": "a924ebe3e6ea7a39374d7d162fd020807cb94900c849c82d286df121db27ee6c", - "after": "c752d35a5b2b2bdc65af5914d89071948e5b10e41772736ade7f89dfd2554a59" - }, - { - "path": "resources/content/schema/user/user-auth.json", - "before": "0f977be3a4e6718753ba8a248e73f1014886afbee1d5387249e762b4146b7b73", - "after": "0f96a7e195647b967d4f83cab74d6a0fc5c442a896baa54384937af765bc2d9e" + "before": "90db2324422f25129edf155127da8e29303b74fe2467797d4459b1df451e9439", + "after": "7acb469f2ffbd0454e7e4e071aa672d3c444140583f41798a6d3cb02a632ba5e" } ] }, @@ -1193,57 +1270,25 @@ "addedTuples": [], "changedTuples": [], "authorizationRationale": { - "certificate": "Only name/description; current native method/field schema, row lock, safe UUID/public fingerprint CAS, Cookie-human approval and original Key revision remain required. No PEM/key/chain field or raw proxy is admitted.", - "nativeNetworkRemoval": "Actual immutable Java execution frames include native processName. Only Instance DELETE/delete, exact persisted owner/UUID/FK and all IP maps qualify for native nic.remove reentry. Missing/stop frames, foreign/shared/reassigned children and explicit NIC/IP/map/service DENY remain denied. Live paths and Full/legacy retain their original owner behavior.", - "terminalDenial": "Only the structured synchronous child AUTHORIZATION_DENIED terminates its parent. Other exit/retry semantics and durable completion-audit replay are unchanged.", - "auditOwnerTopology": "The fixed private CLI shares the configured broker upstream. Java reconstructs only HTTP(S) loopback origins and bounded ports from its exact nonsecret operator setting after clearing all other environment; credentials stay private stdin. No HTTP or tool-specified URL is accepted.", - "audit": "Existing durable metadata-only decision owner includes the explicitly reviewed certificate/externalService/dnsService domains. It does not authorize their operation or log private material." + "serviceIndexRemoval": "Only actual verified service.activate/service.update/service.remove native owners can capture the serviceindex.remove edge. Fresh persisted Index/Service/Stack identities and exact ownership relations must match the original Key-bound root; queued work matches all private identity pins. Missing/wrong parent, foreign/rebound UUID/FK/account, changed Key revision or revoked/expired authority and explicit Index/Service/Stack DENY remain rejected. Full/legacy/no-Key owner behavior is unchanged.", + "operation": "The child retains the original root update/delete operation, rather than obtaining a new independent delete or project-wide resource grant. ServiceIndex is not added to the generic resolver or PROJECT_ONLY.", + "owner": "Planner and Service/Stack remove use the existing native owner. ServiceSuffixRemove keeps its normal pool-only IP allocation release; no new NIC/IP/network or HTTP proxy permission is admitted." }, "sourceInputChanges": [ { - "path": "code/framework/auditing/src/main/java/io/cattle/platform/iaas/api/auditing/AuditServiceImpl.java", - "before": "a10a5d8e7ca754601ea2c5a876c318069b6639c073e616d283ae71694bc95179", - "after": "cb6bb0a8ed3dda48bedd3ae89ed78a490f644c1040c5aa16463e1e701250988e" - }, - { - "path": "code/framework/engine/src/main/java/io/cattle/platform/engine/context/EngineContext.java", - "before": null, - "after": "ba91b4da42d1f2ea5a2b9709818c2a8f4b967c2c730d5681b53d9dbe94ce8968" - }, - { - "path": "code/framework/engine/src/main/java/io/cattle/platform/engine/process/impl/DefaultProcessInstanceImpl.java", - "before": null, - "after": "986e14156ce42ac72033fad21289db4e3732469378cb6c9b0ae1d0a4c36376b0" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQueryRunner.java", - "before": "608fa5f5b412dccdf154290094ff1d67204c092cfb60b850d8d7a3124f53c812", - "after": "684fa84a259118a13d5a1ef20f76e05592ef867492e3fc54c1dcb94c06bb5758" + "path": "code/framework/engine/src/main/java/io/cattle/platform/engine/process/ProcessAuthorization.java", + "before": "a717b03de1ec528f7047161679be436535d68fb416b573c3aaf5b09a2e44b520", + "after": "ae96df57002f8102f1bf5eb3c813574a3563ec9ef52133f3499299037fb29ed3" }, { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyProcessAuthorization.java", - "before": "1bf968d28d977725fa426fe7f32b00d5bc322979c0bfe1e0501fc2c34c03100e", - "after": "39ac76abfff5b7a8d95f722f72a4869443ec9c4e99cac754b2690f7ab5be382d" + "before": "39ac76abfff5b7a8d95f722f72a4869443ec9c4e99cac754b2690f7ab5be382d", + "after": "b2bf0a5939e030de833957f634622fccea75bb8f00f86e454b83f910f695682d" }, { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", - "before": "3c299d683055c0301f93b4bc8d23252215d1d9c0746d0aaafa0b52447d3eb26b", - "after": "e755cdf32b48df5392cc6700e0d86890393828da25f957cdfc60c9e6ce157968" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDescriptor.java", - "before": "2ef7555c7864a2ce91a7c28951e895da412f68849b6cc3ec04350a75b35186f8", - "after": "542f4d8b53b7360a4b72570466f63f027469d5bf2f0e3ce66ea3d6b6ceb6f417" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDomain.java", - "before": "aafe0ea7a5f60f7e9dc926067318cb2d470ec066cc1e5986b76b2c79122570a4", - "after": "2fc7645b2ce573ae02ebc2ec7e20548dda2e0a738d8e65d056650a6c85883c3e" - }, - { - "path": "resources/content/schema/base/aiResourceChangePlan.json", - "before": "90db2324422f25129edf155127da8e29303b74fe2467797d4459b1df451e9439", - "after": "7acb469f2ffbd0454e7e4e071aa672d3c444140583f41798a6d3cb02a632ba5e" + "before": "e755cdf32b48df5392cc6700e0d86890393828da25f957cdfc60c9e6ce157968", + "after": "51b21c88e5ec55dbf2a8708b4890127b9ab9668b3b1659d09a71942f11d25403" } ] }, @@ -1264,25 +1309,15 @@ "addedTuples": [], "changedTuples": [], "authorizationRationale": { - "serviceIndexRemoval": "Only actual verified service.activate/service.update/service.remove native owners can capture the serviceindex.remove edge. Fresh persisted Index/Service/Stack identities and exact ownership relations must match the original Key-bound root; queued work matches all private identity pins. Missing/wrong parent, foreign/rebound UUID/FK/account, changed Key revision or revoked/expired authority and explicit Index/Service/Stack DENY remain rejected. Full/legacy/no-Key owner behavior is unchanged.", - "operation": "The child retains the original root update/delete operation, rather than obtaining a new independent delete or project-wide resource grant. ServiceIndex is not added to the generic resolver or PROJECT_ONLY.", - "owner": "Planner and Service/Stack remove use the existing native owner. ServiceSuffixRemove keeps its normal pool-only IP allocation release; no new NIC/IP/network or HTTP proxy permission is admitted." + "externalReviewBefore": "Only the two existing before-value reads change from absent Java getters to the existing dynamic field accessor. The existing hostname/IP syntax filtering, safe scalar projection, and explicit clearing of the other target mode remain unchanged.", + "operation": "No method, action, public resource, scope grant or operation classification is added or changed.", + "owner": "The native External Service owner, authorization and full data snapshot/CAS remain unchanged." }, "sourceInputChanges": [ { - "path": "code/framework/engine/src/main/java/io/cattle/platform/engine/process/ProcessAuthorization.java", - "before": "a717b03de1ec528f7047161679be436535d68fb416b573c3aaf5b09a2e44b520", - "after": "ae96df57002f8102f1bf5eb3c813574a3563ec9ef52133f3499299037fb29ed3" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyProcessAuthorization.java", - "before": "39ac76abfff5b7a8d95f722f72a4869443ec9c4e99cac754b2690f7ab5be382d", - "after": "b2bf0a5939e030de833957f634622fccea75bb8f00f86e454b83f910f695682d" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", - "before": "e755cdf32b48df5392cc6700e0d86890393828da25f957cdfc60c9e6ce157968", - "after": "51b21c88e5ec55dbf2a8708b4890127b9ab9668b3b1659d09a71942f11d25403" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDomain.java", + "before": "2fc7645b2ce573ae02ebc2ec7e20548dda2e0a738d8e65d056650a6c85883c3e", + "after": "141fa3773edceec3c7f489d10964ebc4db4c8ff4271976f6ee58ac0f342e96a8" } ] }, @@ -1303,15 +1338,25 @@ "addedTuples": [], "changedTuples": [], "authorizationRationale": { - "externalReviewBefore": "Only the two existing before-value reads change from absent Java getters to the existing dynamic field accessor. The existing hostname/IP syntax filtering, safe scalar projection, and explicit clearing of the other target mode remain unchanged.", - "operation": "No method, action, public resource, scope grant or operation classification is added or changed.", - "owner": "The native External Service owner, authorization and full data snapshot/CAS remain unchanged." + "derivedCleanup": "The new path is limited to standalone native container DELETE, its unique current device-0 OS volume, and a NULL-account private image/cache whose complete live reference graph is proven. It does not create a public Image grant or choose FULL policy; explicit root/dependency denies and fresh owner/Key checks still apply.", + "externalTargets": "The collector intentionally includes nonremoved old target maps. Missing or different exact desired hostname is stale/error so the existing bad-unit cleanup removes that map; missing maps remain not started and stop/remove semantics are retained.", + "operation": "The actual re-extracted HTTP tuple set, semantic classification map and frozen role schemas remain identical. Derived authorization and lifecycle behavior changes are reviewed separately and are not described as zero semantic delta." }, "sourceInputChanges": [ { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDomain.java", - "before": "2fc7645b2ce573ae02ebc2ec7e20548dda2e0a738d8e65d056650a6c85883c3e", - "after": "141fa3773edceec3c7f489d10964ebc4db4c8ff4271976f6ee58ac0f342e96a8" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyProcessAuthorization.java", + "before": "b2bf0a5939e030de833957f634622fccea75bb8f00f86e454b83f910f695682d", + "after": "e7301721f6b7eb54084b46b31eeec364aeecd3c1c95cc646eef0b9a3ea20b82c" + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", + "before": "51b21c88e5ec55dbf2a8708b4890127b9ab9668b3b1659d09a71942f11d25403", + "after": "0f836a821b080d7395a1c19f3740a7259112eb8e0126a2a356c233b699091be9" + }, + { + "path": "code/iaas/service-discovery/server/src/main/java/io/cattle/platform/servicediscovery/deployment/impl/unit/ExternalDeploymentUnitInstance.java", + "before": null, + "after": "66182deff7e2e7aefa36beae2558690c81a130e2ad43025fd899cfa96f06955f" } ] }, @@ -1332,25 +1377,31 @@ "addedTuples": [], "changedTuples": [], "authorizationRationale": { - "derivedCleanup": "The new path is limited to standalone native container DELETE, its unique current device-0 OS volume, and a NULL-account private image/cache whose complete live reference graph is proven. It does not create a public Image grant or choose FULL policy; explicit root/dependency denies and fresh owner/Key checks still apply.", - "externalTargets": "The collector intentionally includes nonremoved old target maps. Missing or different exact desired hostname is stale/error so the existing bad-unit cleanup removes that map; missing maps remain not started and stop/remove semantics are retained.", - "operation": "The actual re-extracted HTTP tuple set, semantic classification map and frozen role schemas remain identical. Derived authorization and lifecycle behavior changes are reviewed separately and are not described as zero semantic delta." + "derivedCleanup": "Only the standalone private OS map job is extended. Direct and nested true parent frames pin instance/volume/map/pool UUIDs and account/stack/FKs before detachment. Historical ancestors are read only after complete original pins and a trusted persisted child agree. Current owner/role/schema, fresh credential/revision/expiry and every root/dependency explicit DENY remain enforced. Missing refs, rebound graph, shared/named/managed storage and old canceled unbound jobs gain no authority. Existing live ancillary paths keep their prior generic authorization.", + "aliasValidation": "Existing native request validation errors retain 422 InvalidBody at the typed preview boundary, before plan allocation/apply. It does not grant access to foreign resources or add a route.", + "operation": "The actual re-extracted production HTTP tuple union, classifications and frozen role schemas remain identical. The authority c03-source-inputs-v1 selector is unchanged except the explicit EngineContext.java anchor.", + "regressionEvidence": "Regression test sources are separate proof, excluded from production authority HTTP input count and tuple extraction. Exact path/SHA: code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/apikey/StandaloneVolumePoolCleanupTest.java=e0017c0d1aa2d453cac4ca8a214e6d37e9f414ef7c1d19e599763a46755c305a; code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDomainTest.java=920ff179d4a0345708c32b516f974a6b8620bd48516cab98062be9d12402402f; code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanServiceTest.java=d09ba2736e5f77a68dbd6dc3f365567cddf22fefef5372deabd934c19341adcd. Required original CI executed methods and qualified wholeTree are the official execution/source evidence, not this metadata review." }, "sourceInputChanges": [ + { + "path": "code/framework/engine/src/main/java/io/cattle/platform/engine/context/EngineContext.java", + "before": "ba91b4da42d1f2ea5a2b9709818c2a8f4b967c2c730d5681b53d9dbe94ce8968", + "after": "17df7120c6b4a5e78ca643d0ea26f0fa30023bc277f2eb3b155680a97bef6b3b" + }, { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyProcessAuthorization.java", - "before": "b2bf0a5939e030de833957f634622fccea75bb8f00f86e454b83f910f695682d", - "after": "e7301721f6b7eb54084b46b31eeec364aeecd3c1c95cc646eef0b9a3ea20b82c" + "before": "e7301721f6b7eb54084b46b31eeec364aeecd3c1c95cc646eef0b9a3ea20b82c", + "after": "0a102044c31c53be38095526812e8c36aa463ada9e32f5e58042a20e51e3216f" }, { "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", - "before": "51b21c88e5ec55dbf2a8708b4890127b9ab9668b3b1659d09a71942f11d25403", - "after": "0f836a821b080d7395a1c19f3740a7259112eb8e0126a2a356c233b699091be9" + "before": "0f836a821b080d7395a1c19f3740a7259112eb8e0126a2a356c233b699091be9", + "after": "76742db7c623e670415d14790daa3913f51ae1182737caa459c10d83d3a4abd4" }, { - "path": "code/iaas/service-discovery/server/src/main/java/io/cattle/platform/servicediscovery/deployment/impl/unit/ExternalDeploymentUnitInstance.java", - "before": null, - "after": "66182deff7e2e7aefa36beae2558690c81a130e2ad43025fd899cfa96f06955f" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanService.java", + "before": "d0605f3e94757996e699e4083b1cd314d6d68acf623358a92f9841bc75384fb9", + "after": "bfeb2e89f4a3049ec70292e14e29b2a74b4302f8756e80954edb2fdbe6497f0d" } ] }, @@ -1371,31 +1422,15 @@ "addedTuples": [], "changedTuples": [], "authorizationRationale": { - "derivedCleanup": "Only the standalone private OS map job is extended. Direct and nested true parent frames pin instance/volume/map/pool UUIDs and account/stack/FKs before detachment. Historical ancestors are read only after complete original pins and a trusted persisted child agree. Current owner/role/schema, fresh credential/revision/expiry and every root/dependency explicit DENY remain enforced. Missing refs, rebound graph, shared/named/managed storage and old canceled unbound jobs gain no authority. Existing live ancillary paths keep their prior generic authorization.", - "aliasValidation": "Existing native request validation errors retain 422 InvalidBody at the typed preview boundary, before plan allocation/apply. It does not grant access to foreign resources or add a route.", - "operation": "The actual re-extracted production HTTP tuple union, classifications and frozen role schemas remain identical. The authority c03-source-inputs-v1 selector is unchanged except the explicit EngineContext.java anchor.", - "regressionEvidence": "Regression test sources are separate proof, excluded from production authority HTTP input count and tuple extraction. Exact path/SHA: code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/apikey/StandaloneVolumePoolCleanupTest.java=e0017c0d1aa2d453cac4ca8a214e6d37e9f414ef7c1d19e599763a46755c305a; code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDomainTest.java=920ff179d4a0345708c32b516f974a6b8620bd48516cab98062be9d12402402f; code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanServiceTest.java=d09ba2736e5f77a68dbd6dc3f365567cddf22fefef5372deabd934c19341adcd. Required original CI executed methods and qualified wholeTree are the official execution/source evidence, not this metadata review." + "privateWire": "Consumer compatibility correction only; existing current actor, owner, role, Key revision/expiry, approval, dependency DENY and dispatch gates are unchanged. No raw JSON or nested Base64 fallback.", + "operation": "Existing production-only c03-source-inputs-v1 selector, explicit anchors, HTTP tuples, classifications and role schemas remain exact.", + "regressionEvidence": "Separate test proof, excluded from production authority HTTP count: code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchDelegationTest.java=78f4a0cc3d366ed83987f113b8212e1019943d12539947dda6c6760f07cb6c9b; code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPrivateTest.java=1f855b3b8d832cce524aa7743ce24db98265e051dcb9e97ec056baf0157e804e; code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPrivateWireTest.java=257599b8217e60d99c1cd1ce182540b5361ac64539b02685425ecfd55e94154b; code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchWorkflowTest.java=d73681c1e2c8b42e19e4228635005543bf1a2d708d1603eda6f07407620e0d5d. Official execution proof remains required original CI plus qualified wholeTree; local synthetic loopback tests are not runtime acceptance." }, "sourceInputChanges": [ { - "path": "code/framework/engine/src/main/java/io/cattle/platform/engine/context/EngineContext.java", - "before": "ba91b4da42d1f2ea5a2b9709818c2a8f4b967c2c730d5681b53d9dbe94ce8968", - "after": "17df7120c6b4a5e78ca643d0ea26f0fa30023bc277f2eb3b155680a97bef6b3b" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyProcessAuthorization.java", - "before": "e7301721f6b7eb54084b46b31eeec364aeecd3c1c95cc646eef0b9a3ea20b82c", - "after": "0a102044c31c53be38095526812e8c36aa463ada9e32f5e58042a20e51e3216f" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/apikey/ApiKeyTargetResolver.java", - "before": "0f836a821b080d7395a1c19f3740a7259112eb8e0126a2a356c233b699091be9", - "after": "76742db7c623e670415d14790daa3913f51ae1182737caa459c10d83d3a4abd4" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanService.java", - "before": "d0605f3e94757996e699e4083b1cd314d6d68acf623358a92f9841bc75384fb9", - "after": "bfeb2e89f4a3049ec70292e14e29b2a74b4302f8756e80954edb2fdbe6497f0d" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPrivate.java", + "before": "df91328e28fca5f15aceda4faaf57be47c8165dfc5cbf36894abd12935c8d3b2", + "after": "a1f341587843e47beacf4c8d220ea3724f30c779a057555e7eccb33a2dfd2c71" } ] }, @@ -1416,17 +1451,152 @@ "addedTuples": [], "changedTuples": [], "authorizationRationale": { - "privateWire": "Consumer compatibility correction only; existing current actor, owner, role, Key revision/expiry, approval, dependency DENY and dispatch gates are unchanged. No raw JSON or nested Base64 fallback.", - "operation": "Existing production-only c03-source-inputs-v1 selector, explicit anchors, HTTP tuples, classifications and role schemas remain exact.", - "regressionEvidence": "Separate test proof, excluded from production authority HTTP count: code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchDelegationTest.java=78f4a0cc3d366ed83987f113b8212e1019943d12539947dda6c6760f07cb6c9b; code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPrivateTest.java=1f855b3b8d832cce524aa7743ce24db98265e051dcb9e97ec056baf0157e804e; code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPrivateWireTest.java=257599b8217e60d99c1cd1ce182540b5361ac64539b02685425ecfd55e94154b; code/iaas/auth-logic/src/test/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchWorkflowTest.java=d73681c1e2c8b42e19e4228635005543bf1a2d708d1603eda6f07407620e0d5d. Official execution proof remains required original CI plus qualified wholeTree; local synthetic loopback tests are not runtime acceptance." + "typedCreate": "Only ports and the closed healthCheck subset enter the existing Service create adapter. Current actor/project/role/key max/revision/expiry/CAS, human approval, audit and one durable claim remain; environment and raw launchConfig remain rejected.", + "executionResult": "admin/project/user gain r only on a new read-only result field, never create/update. Existing receipt access still reauthorizes the actual same-account Service and pins ID/UUID. assignedPorts is emitted only after exact readback succeeds; approved changes remain immutable.", + "nativeOwners": "ServiceValidationFilter, PortSpec, PortPreflightInputs/Service, PortBindingAddress, ServiceCreate and ServiceDiscoveryServiceImpl are now source-bound alongside AiServiceCreateChange and ServiceCreateValidation. The same parser, preflight and persisted allocation owner remain authoritative.", + "operation": "1396 exact tuples and every derived semantic/registered/unsupported/human-only disposition are unchanged. Frozen v1 schemas and all existing role permissions are unchanged except the three explicit new r projection entries.", + "catalogProjection": "A fresh copy of InstanceRecord data.fields feeds the existing native role-schema projection with the same formatter/POST and non-create-response rules; it preserves already-authorized business values without introducing a new permission or transport.", + "acceptance": "Source extraction is not artifact, role-matrix, HTTP or asynchronous runtime acceptance; the original PR149/CI failure remains preserved." }, "sourceInputChanges": [ { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPrivate.java", - "before": "df91328e28fca5f15aceda4faaf57be47c8165dfc5cbf36894abd12935c8d3b2", - "after": "a1f341587843e47beacf4c8d220ea3724f30c779a057555e7eccb33a2dfd2c71" + "path": "code/iaas/api-logic/src/main/java/io/cattle/platform/iaas/api/port/PortPreflightInputs.java", + "before": null, + "after": "237060330f0ae0c092b11018159b6bf9fa214e1e2564d57f6b139dee34c38e13", + "baselineSourceSha256": "237060330f0ae0c092b11018159b6bf9fa214e1e2564d57f6b139dee34c38e13", + "newlyBound": true, + "sourceBytesChanged": false + }, + { + "path": "code/iaas/api-logic/src/main/java/io/cattle/platform/iaas/api/port/PortPreflightService.java", + "before": null, + "after": "6a64ad664eee2f5817e6157b5564f72ac3381cb7f0881e2ef73bab6b80c3a110", + "baselineSourceSha256": "6a64ad664eee2f5817e6157b5564f72ac3381cb7f0881e2ef73bab6b80c3a110", + "newlyBound": true, + "sourceBytesChanged": false + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchMaterializer.java", + "before": "00945aae0ccd8091f6835168bd0d0ff7615be2f00cc86c27f48218520d680f50", + "after": "26aa70893a8182f191f9b4d02d0f68a04ec4da6017b83e1d4726a8327ee93781", + "baselineSourceSha256": "00945aae0ccd8091f6835168bd0d0ff7615be2f00cc86c27f48218520d680f50", + "newlyBound": false, + "sourceBytesChanged": true + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDescriptor.java", + "before": "542f4d8b53b7360a4b72570466f63f027469d5bf2f0e3ce66ea3d6b6ceb6f417", + "after": "c60650a74476af5faadd8cc76bcab4d073fd294dfac28d8dc176c07daeb7d4dc", + "baselineSourceSha256": "542f4d8b53b7360a4b72570466f63f027469d5bf2f0e3ce66ea3d6b6ceb6f417", + "newlyBound": false, + "sourceBytesChanged": true + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDomain.java", + "before": "141fa3773edceec3c7f489d10964ebc4db4c8ff4271976f6ee58ac0f342e96a8", + "after": "fc2245d42e31f3426fef91d68bbe8039f67f50b0a47b9e60cd003c83d1776ad0", + "baselineSourceSha256": "141fa3773edceec3c7f489d10964ebc4db4c8ff4271976f6ee58ac0f342e96a8", + "newlyBound": false, + "sourceBytesChanged": true + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanService.java", + "before": "bfeb2e89f4a3049ec70292e14e29b2a74b4302f8756e80954edb2fdbe6497f0d", + "after": "1d52b18a6b3efc5f86b30e52cb1ab57bb27f788e28703a4e7864d473dd7aa071", + "baselineSourceSha256": "bfeb2e89f4a3049ec70292e14e29b2a74b4302f8756e80954edb2fdbe6497f0d", + "newlyBound": false, + "sourceBytesChanged": true + }, + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiServiceCreateChange.java", + "before": null, + "after": "ac42a7cf1108ae29791ba3198c7602f5fdc4f786e5eb9cd278581fe23831be4f", + "baselineSourceSha256": null, + "newlyBound": true, + "sourceBytesChanged": true + }, + { + "path": "code/iaas/model/src/main/java/io/cattle/platform/core/util/PortBindingAddress.java", + "before": null, + "after": "e263eaaaeacc6bad7d09a9e21b48cafa098ced410857b8ab55dc1bab21ffccd4", + "baselineSourceSha256": "e263eaaaeacc6bad7d09a9e21b48cafa098ced410857b8ab55dc1bab21ffccd4", + "newlyBound": true, + "sourceBytesChanged": false + }, + { + "path": "code/iaas/model/src/main/java/io/cattle/platform/core/util/PortSpec.java", + "before": null, + "after": "66d88b6af51001ce9a49d0b47d9031c2fb0c076ff60b75b4f6b30473da64bd9e", + "baselineSourceSha256": "19c50738b291e64f425a05e58d781389cba151933d9741e9ab7f0b5a11a0d734", + "newlyBound": true, + "sourceBytesChanged": true + }, + { + "path": "code/iaas/service-discovery/api/src/main/java/io/cattle/platform/servicediscovery/api/filter/ServiceValidationFilter.java", + "before": null, + "after": "39d55237e452e7dbec7122eed74bee22d01f4db79e0f5c70ea26c28509f83107", + "baselineSourceSha256": "57e69c59889ca0d9cb5956659755625f923e0f67af57d428471f0247b2683575", + "newlyBound": true, + "sourceBytesChanged": true + }, + { + "path": "code/iaas/service-discovery/api/src/main/java/io/cattle/platform/servicediscovery/api/service/ServiceCreateValidation.java", + "before": null, + "after": "663e4a276a68636e4d5284cfb7b4fd80301d733f4a410775e4f6d7ae34e9a143", + "baselineSourceSha256": null, + "newlyBound": true, + "sourceBytesChanged": true + }, + { + "path": "code/iaas/service-discovery/server/src/main/java/io/cattle/platform/servicediscovery/process/ServiceCreate.java", + "before": null, + "after": "4c04eed9b5cc6cab4cf46b3c165021c9d15c3feecaf418f44377261d4e415157", + "baselineSourceSha256": "4c04eed9b5cc6cab4cf46b3c165021c9d15c3feecaf418f44377261d4e415157", + "newlyBound": true, + "sourceBytesChanged": false + }, + { + "path": "code/iaas/service-discovery/server/src/main/java/io/cattle/platform/servicediscovery/service/impl/ServiceDiscoveryServiceImpl.java", + "before": null, + "after": "0300fb72cd8f5a1a06c3d26509a9d74c79c644d1aab0c1ce16fa46357a8b1039", + "baselineSourceSha256": "0300fb72cd8f5a1a06c3d26509a9d74c79c644d1aab0c1ce16fa46357a8b1039", + "newlyBound": true, + "sourceBytesChanged": false + }, + { + "path": "resources/content/schema/admin/admin-auth.json", + "before": "27630fdb4d5cf7a1dcd7e693b84d0b31513d627a64a5d2365119075aca6d4f85", + "after": "f713ba64c53fb498b2cbe7f96b5c794ed35d093a74a78cafcffe3f19b59ef5df", + "baselineSourceSha256": "27630fdb4d5cf7a1dcd7e693b84d0b31513d627a64a5d2365119075aca6d4f85", + "newlyBound": false, + "sourceBytesChanged": true + }, + { + "path": "resources/content/schema/base/aiResourceChangePlan.json", + "before": "7acb469f2ffbd0454e7e4e071aa672d3c444140583f41798a6d3cb02a632ba5e", + "after": "113f44df62f09f822b7f97f4cfdcab96de2f0f70995c821632f801c20134110c", + "baselineSourceSha256": "7acb469f2ffbd0454e7e4e071aa672d3c444140583f41798a6d3cb02a632ba5e", + "newlyBound": false, + "sourceBytesChanged": true + }, + { + "path": "resources/content/schema/project/project-auth.json", + "before": "c752d35a5b2b2bdc65af5914d89071948e5b10e41772736ade7f89dfd2554a59", + "after": "ce1ebde019bfd57d6ddd5c2b77d119a76e1df38bf887371e765478c3d96388cf", + "baselineSourceSha256": "c752d35a5b2b2bdc65af5914d89071948e5b10e41772736ade7f89dfd2554a59", + "newlyBound": false, + "sourceBytesChanged": true + }, + { + "path": "resources/content/schema/user/user-auth.json", + "before": "0f96a7e195647b967d4f83cab74d6a0fc5c442a896baa54384937af765bc2d9e", + "after": "66a82fa448806fb826ecd7a11bc9dc6cc9598e7a221d63191113457fd3376091", + "baselineSourceSha256": "0f96a7e195647b967d4f83cab74d6a0fc5c442a896baa54384937af765bc2d9e", + "newlyBound": false, + "sourceBytesChanged": true } - ] + ], + "reviewManifest": "scripts/api-key-operation-review-0.183.366.json" }, "schemas": [ "resources/content/schema/base/aiServiceDescriptionUpdate.json", @@ -1444,153 +1614,223 @@ ], "addedTuples": [], "changedTuples": [], - "authorizationRationale": { - "typedCreate": "Only ports and the closed healthCheck subset enter the existing Service create adapter. Current actor/project/role/key max/revision/expiry/CAS, human approval, audit and one durable claim remain; environment and raw launchConfig remain rejected.", - "executionResult": "admin/project/user gain r only on a new read-only result field, never create/update. Existing receipt access still reauthorizes the actual same-account Service and pins ID/UUID. assignedPorts is emitted only after exact readback succeeds; approved changes remain immutable.", - "nativeOwners": "ServiceValidationFilter, PortSpec, PortPreflightInputs/Service, PortBindingAddress, ServiceCreate and ServiceDiscoveryServiceImpl are now source-bound alongside AiServiceCreateChange and ServiceCreateValidation. The same parser, preflight and persisted allocation owner remain authoritative.", - "operation": "1396 exact tuples and every derived semantic/registered/unsupported/human-only disposition are unchanged. Frozen v1 schemas and all existing role permissions are unchanged except the three explicit new r projection entries.", - "catalogProjection": "A fresh copy of InstanceRecord data.fields feeds the existing native role-schema projection with the same formatter/POST and non-create-response rules; it preserves already-authorized business values without introducing a new permission or transport.", - "acceptance": "Source extraction is not artifact, role-matrix, HTTP or asynchronous runtime acceptance; the original PR149/CI failure remains preserved." - }, "sourceInputChanges": [ { - "path": "code/iaas/api-logic/src/main/java/io/cattle/platform/iaas/api/port/PortPreflightInputs.java", + "path": "code/iaas/api-logic/src/main/java/io/cattle/platform/iaas/api/volume/VolumePreflightInputs.java", + "before": null, + "after": "dffdce7b133cf1bc16b410c32f365a6fee5ce807e79802a2b3d52a98da1dfc02", + "newlyBound": true, + "baselineSourceSha256": "dffdce7b133cf1bc16b410c32f365a6fee5ce807e79802a2b3d52a98da1dfc02" + }, + { + "path": "code/iaas/api-logic/src/main/java/io/cattle/platform/iaas/api/volume/VolumePreflightService.java", "before": null, - "after": "237060330f0ae0c092b11018159b6bf9fa214e1e2564d57f6b139dee34c38e13", - "baselineSourceSha256": "237060330f0ae0c092b11018159b6bf9fa214e1e2564d57f6b139dee34c38e13", + "after": "4f2a93e0e00abb68277d09351a0a85c7fa201bd8e1d07e2bbbd8bcaaa5ce18e2", "newlyBound": true, - "sourceBytesChanged": false + "baselineSourceSha256": "4f2a93e0e00abb68277d09351a0a85c7fa201bd8e1d07e2bbbd8bcaaa5ce18e2" }, { - "path": "code/iaas/api-logic/src/main/java/io/cattle/platform/iaas/api/port/PortPreflightService.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQueryInputHandler.java", "before": null, - "after": "6a64ad664eee2f5817e6157b5564f72ac3381cb7f0881e2ef73bab6b80c3a110", - "baselineSourceSha256": "6a64ad664eee2f5817e6157b5564f72ac3381cb7f0881e2ef73bab6b80c3a110", + "after": "46abd6c96d543f84b3884d1dafd4f41db9f6111e0edf9f770a8289f5604390a1", "newlyBound": true, - "sourceBytesChanged": false + "baselineSourceSha256": null }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchMaterializer.java", - "before": "00945aae0ccd8091f6835168bd0d0ff7615be2f00cc86c27f48218520d680f50", - "after": "26aa70893a8182f191f9b4d02d0f68a04ec4da6017b83e1d4726a8327ee93781", - "baselineSourceSha256": "00945aae0ccd8091f6835168bd0d0ff7615be2f00cc86c27f48218520d680f50", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQueryService.java", + "before": "4067cc8685399b2b2bfb9e7b5eaddd10b906f63fccf286ef7e118622e4e80ea6", + "after": "01f316fb38aefd1e43f81773dab71576ff53ef37c4b8a9e844ae6d2556df3aca", "newlyBound": false, - "sourceBytesChanged": true + "baselineSourceSha256": "4067cc8685399b2b2bfb9e7b5eaddd10b906f63fccf286ef7e118622e4e80ea6" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDescriptor.java", - "before": "542f4d8b53b7360a4b72570466f63f027469d5bf2f0e3ce66ea3d6b6ceb6f417", - "after": "c60650a74476af5faadd8cc76bcab4d073fd294dfac28d8dc176c07daeb7d4dc", - "baselineSourceSha256": "542f4d8b53b7360a4b72570466f63f027469d5bf2f0e3ce66ea3d6b6ceb6f417", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchAccess.java", + "before": "639ceb2151b6668af77ff2f71ead2cd7699d76d45c17521e46a90af624286b52", + "after": "5f0e1de8995318226e0c8ae48acbd3a6e07b025e7fa068daa1bc5945e25c6d49", "newlyBound": false, - "sourceBytesChanged": true + "baselineSourceSha256": "639ceb2151b6668af77ff2f71ead2cd7699d76d45c17521e46a90af624286b52" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDomain.java", - "before": "141fa3773edceec3c7f489d10964ebc4db4c8ff4271976f6ee58ac0f342e96a8", - "after": "fc2245d42e31f3426fef91d68bbe8039f67f50b0a47b9e60cd003c83d1776ad0", - "baselineSourceSha256": "141fa3773edceec3c7f489d10964ebc4db4c8ff4271976f6ee58ac0f342e96a8", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPlanResourceManager.java", + "before": "ef70bb6e029fdb446358ad81e9f791f14e892c28bda754b8ce479077fb85ff98", + "after": "b81b7e746d7557bd740b164123bd7584cf399b8b5a2bd57e258535392fe67b3d", "newlyBound": false, - "sourceBytesChanged": true + "baselineSourceSha256": "ef70bb6e029fdb446358ad81e9f791f14e892c28bda754b8ce479077fb85ff98" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanService.java", - "before": "bfeb2e89f4a3049ec70292e14e29b2a74b4302f8756e80954edb2fdbe6497f0d", - "after": "1d52b18a6b3efc5f86b30e52cb1ab57bb27f788e28703a4e7864d473dd7aa071", - "baselineSourceSha256": "bfeb2e89f4a3049ec70292e14e29b2a74b4302f8756e80954edb2fdbe6497f0d", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPlanService.java", + "before": "77b8f8b2b4ade110064ba0a874db04c1d5adbfe9df68655b8760c395270a05e3", + "after": "119c0347b3e6b984a76e1250fb2d2fee79337b77b13ed9dd87d888518efa818a", "newlyBound": false, - "sourceBytesChanged": true + "baselineSourceSha256": "77b8f8b2b4ade110064ba0a874db04c1d5adbfe9df68655b8760c395270a05e3" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiServiceCreateChange.java", - "before": null, - "after": "ac42a7cf1108ae29791ba3198c7602f5fdc4f786e5eb9cd278581fe23831be4f", - "baselineSourceSha256": null, - "newlyBound": true, - "sourceBytesChanged": true + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanResourceManager.java", + "before": "37da81bdccdb528c1d7f1b18217d3896cabd0ad601e6a3809fd50913b6613050", + "after": "17ba569ba4f5265d7d3a8e50cc3ce2d21d220232c354e169be511b74ce212b17", + "newlyBound": false, + "baselineSourceSha256": "37da81bdccdb528c1d7f1b18217d3896cabd0ad601e6a3809fd50913b6613050" }, { - "path": "code/iaas/model/src/main/java/io/cattle/platform/core/util/PortBindingAddress.java", - "before": null, - "after": "e263eaaaeacc6bad7d09a9e21b48cafa098ced410857b8ab55dc1bab21ffccd4", - "baselineSourceSha256": "e263eaaaeacc6bad7d09a9e21b48cafa098ced410857b8ab55dc1bab21ffccd4", - "newlyBound": true, - "sourceBytesChanged": false + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanService.java", + "before": "1d52b18a6b3efc5f86b30e52cb1ab57bb27f788e28703a4e7864d473dd7aa071", + "after": "1b920af86f0294b1c1e1ee44f4a9b7dc9bf7eac9e269298a1007c8ff235e6d45", + "newlyBound": false, + "baselineSourceSha256": "1d52b18a6b3efc5f86b30e52cb1ab57bb27f788e28703a4e7864d473dd7aa071" }, { - "path": "code/iaas/model/src/main/java/io/cattle/platform/core/util/PortSpec.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/upgrade/AiServiceUpgradePlanInputHandler.java", "before": null, - "after": "66d88b6af51001ce9a49d0b47d9031c2fb0c076ff60b75b4f6b30473da64bd9e", - "baselineSourceSha256": "19c50738b291e64f425a05e58d781389cba151933d9741e9ab7f0b5a11a0d734", + "after": "a38c9fece7444a5fd5385b48f9b9ca2997e8218c82c91096473115cc87ee69aa", "newlyBound": true, - "sourceBytesChanged": true + "baselineSourceSha256": null }, { - "path": "code/iaas/service-discovery/api/src/main/java/io/cattle/platform/servicediscovery/api/filter/ServiceValidationFilter.java", - "before": null, - "after": "39d55237e452e7dbec7122eed74bee22d01f4db79e0f5c70ea26c28509f83107", - "baselineSourceSha256": "57e69c59889ca0d9cb5956659755625f923e0f67af57d428471f0247b2683575", - "newlyBound": true, - "sourceBytesChanged": true + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/upgrade/AiServiceUpgradePlanResourceManager.java", + "before": "51ac797f47ba68e52d360c6c53bb3aa143e33a637286deca9636f5d55559f1a8", + "after": "30cb1cdae0766c0f0a6c7f3f4c27187ca0bd565002bda4e311368e420e88d9a7", + "newlyBound": false, + "baselineSourceSha256": "51ac797f47ba68e52d360c6c53bb3aa143e33a637286deca9636f5d55559f1a8" }, { - "path": "code/iaas/service-discovery/api/src/main/java/io/cattle/platform/servicediscovery/api/service/ServiceCreateValidation.java", + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/upgrade/AiServiceUpgradePlanService.java", "before": null, - "after": "663e4a276a68636e4d5284cfb7b4fd80301d733f4a410775e4f6d7ae34e9a143", - "baselineSourceSha256": null, + "after": "7398ac81e4287ee2e950d2b86b8ce55fd574d8af40831044553514e729d8204d", "newlyBound": true, - "sourceBytesChanged": true + "baselineSourceSha256": "12782760bbd8e600c06876006e39ff9e7f3de818ffb8e39a5e294f9484579a8a" }, { - "path": "code/iaas/service-discovery/server/src/main/java/io/cattle/platform/servicediscovery/process/ServiceCreate.java", - "before": null, - "after": "4c04eed9b5cc6cab4cf46b3c165021c9d15c3feecaf418f44377261d4e415157", - "baselineSourceSha256": "4c04eed9b5cc6cab4cf46b3c165021c9d15c3feecaf418f44377261d4e415157", - "newlyBound": true, - "sourceBytesChanged": false + "path": "code/iaas/service-discovery/api/src/main/java/io/cattle/platform/servicediscovery/api/filter/ServiceUpgradeValidationFilter.java", + "before": "27cea9ff5e7efc030de24d0095669fa5812a7931d64bcdbf8dfefb8888d7db36", + "after": "1adcf76557b3392161a46393d795b67a0ccc781a49d544fa8672aafe49475a63", + "newlyBound": false, + "baselineSourceSha256": "27cea9ff5e7efc030de24d0095669fa5812a7931d64bcdbf8dfefb8888d7db36" }, { - "path": "code/iaas/service-discovery/server/src/main/java/io/cattle/platform/servicediscovery/service/impl/ServiceDiscoveryServiceImpl.java", + "path": "code/iaas/service-discovery/api/src/main/java/io/cattle/platform/servicediscovery/api/service/ServiceUpgradeValidation.java", "before": null, - "after": "0300fb72cd8f5a1a06c3d26509a9d74c79c644d1aab0c1ce16fa46357a8b1039", - "baselineSourceSha256": "0300fb72cd8f5a1a06c3d26509a9d74c79c644d1aab0c1ce16fa46357a8b1039", + "after": "ffcf91e17f0aaffe821acf297d1e125768a5332c062c1bf5c435114035255cf1", "newlyBound": true, - "sourceBytesChanged": false + "baselineSourceSha256": null + }, + { + "path": "code/packaging/app-config/src/main/java/io/cattle/platform/app/IaasApiConfig.java", + "before": "59b633a3f6614f811b5f14b0eeeeb1f99683d319a2c28bea2093f48a33a53130", + "after": "fa64b48420abe59930c464283a773d2dfcccbaeea152fdf1a997d8dcae184e9a", + "newlyBound": false, + "baselineSourceSha256": "59b633a3f6614f811b5f14b0eeeeb1f99683d319a2c28bea2093f48a33a53130" }, { "path": "resources/content/schema/admin/admin-auth.json", - "before": "27630fdb4d5cf7a1dcd7e693b84d0b31513d627a64a5d2365119075aca6d4f85", - "after": "f713ba64c53fb498b2cbe7f96b5c794ed35d093a74a78cafcffe3f19b59ef5df", - "baselineSourceSha256": "27630fdb4d5cf7a1dcd7e693b84d0b31513d627a64a5d2365119075aca6d4f85", + "before": "f713ba64c53fb498b2cbe7f96b5c794ed35d093a74a78cafcffe3f19b59ef5df", + "after": "0282ac1900b37648214fc48dce394e00c1b22cc27340e08612d5e5e81ca66f64", "newlyBound": false, - "sourceBytesChanged": true + "baselineSourceSha256": "f713ba64c53fb498b2cbe7f96b5c794ed35d093a74a78cafcffe3f19b59ef5df" }, { - "path": "resources/content/schema/base/aiResourceChangePlan.json", - "before": "7acb469f2ffbd0454e7e4e071aa672d3c444140583f41798a6d3cb02a632ba5e", - "after": "113f44df62f09f822b7f97f4cfdcab96de2f0f70995c821632f801c20134110c", - "baselineSourceSha256": "7acb469f2ffbd0454e7e4e071aa672d3c444140583f41798a6d3cb02a632ba5e", + "path": "resources/content/schema/base/aiServiceUpgradePlan.json", + "before": "025cd4a0b044cda9f2500a79a99b605c867f95e8f69d46997ed843b221d67cb6", + "after": "5285ad2caab0e05e28fed27299e5ad114e84c15820bba9a9cfbfc45a163b62d0", "newlyBound": false, - "sourceBytesChanged": true + "baselineSourceSha256": "025cd4a0b044cda9f2500a79a99b605c867f95e8f69d46997ed843b221d67cb6" }, { "path": "resources/content/schema/project/project-auth.json", - "before": "c752d35a5b2b2bdc65af5914d89071948e5b10e41772736ade7f89dfd2554a59", - "after": "ce1ebde019bfd57d6ddd5c2b77d119a76e1df38bf887371e765478c3d96388cf", - "baselineSourceSha256": "c752d35a5b2b2bdc65af5914d89071948e5b10e41772736ade7f89dfd2554a59", + "before": "ce1ebde019bfd57d6ddd5c2b77d119a76e1df38bf887371e765478c3d96388cf", + "after": "8ba8e18dca27a9cc65208c49a5ab72f3ff3d4d4353ae6b8d6891a2f913a76f09", "newlyBound": false, - "sourceBytesChanged": true + "baselineSourceSha256": "ce1ebde019bfd57d6ddd5c2b77d119a76e1df38bf887371e765478c3d96388cf" }, { "path": "resources/content/schema/user/user-auth.json", - "before": "0f96a7e195647b967d4f83cab74d6a0fc5c442a896baa54384937af765bc2d9e", - "after": "66a82fa448806fb826ecd7a11bc9dc6cc9598e7a221d63191113457fd3376091", - "baselineSourceSha256": "0f96a7e195647b967d4f83cab74d6a0fc5c442a896baa54384937af765bc2d9e", + "before": "66a82fa448806fb826ecd7a11bc9dc6cc9598e7a221d63191113457fd3376091", + "after": "4f54ea9c4b8b2d7d7e849e17a73f33d7262f2519e8263e28842ee7eaec414835", "newlyBound": false, - "sourceBytesChanged": true + "baselineSourceSha256": "66a82fa448806fb826ecd7a11bc9dc6cc9598e7a221d63191113457fd3376091" + } + ], + "roleFieldDelta": [ + { + "path": "resources/content/schema/admin/admin-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.startFirst", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/admin/admin-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.batchSize", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/admin/admin-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/admin/admin-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", + "before": null, + "after": "r" + }, + { + "path": "resources/content/schema/project/project-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.startFirst", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/project/project-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.batchSize", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/project/project-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/project/project-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", + "before": null, + "after": "r" + }, + { + "path": "resources/content/schema/user/user-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.startFirst", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/user/user-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.batchSize", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/user/user-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/user/user-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", + "before": null, + "after": "r" } ], - "reviewManifest": "scripts/api-key-operation-review-0.183.366.json" + "authorizationRationale": { + "operation": "1396 exact tuples and each semantic/registered/unsupported/human-only disposition unchanged.", + "strategy": "Only existing upgrade-plan roles accept three optional scalar fields; dispatch still uses the original authorized native manager. No target or scope grant is added.", + "preflight": "Existing native filter implements the shared read-only interface. Native strategy invariants, including retain-IP/start-first, and the same port/volume rules run at preview/confirmation/apply; native batch normalization and original validation errors remain unchanged, including their canonical DENY reason.", + "audit": "Exact typed audit collection only; a sticky boolean retains the original closed-field rejection, and the existing owner audits ERROR without invoking its runner. No raw payload is retained.", + "acceptance": "Source extraction does not establish artifact, role matrix, HTTP/UI or asynchronous runtime acceptance.", + "nativeActionOperandLookup": "Native Catalog-launch, resource-change and upgrade action operands use only exact framework request markers and authorized read snapshots. No prefetch observation writes or retained plan/credential row locks precede the action application lock. Ordinary GET observation and final action owner, role, Key revision, source/snapshot, CAS and one-claim checks remain; no timeout, retry, schema or grant expansion. New upgrade plans bind the complete strategy in their private target snapshot so older engines reject them before claim; genuine legacy image-only plans keep classic snapshots and original defaults." + } }, "schemas": [ "resources/content/schema/base/aiServiceDescriptionUpdate.json", @@ -1610,259 +1850,43 @@ "changedTuples": [], "sourceInputChanges": [ { - "path": "code/iaas/api-logic/src/main/java/io/cattle/platform/iaas/api/volume/VolumePreflightInputs.java", - "before": null, - "after": "dffdce7b133cf1bc16b410c32f365a6fee5ce807e79802a2b3d52a98da1dfc02", - "newlyBound": true, - "baselineSourceSha256": "dffdce7b133cf1bc16b410c32f365a6fee5ce807e79802a2b3d52a98da1dfc02" - }, - { - "path": "code/iaas/api-logic/src/main/java/io/cattle/platform/iaas/api/volume/VolumePreflightService.java", - "before": null, - "after": "4f2a93e0e00abb68277d09351a0a85c7fa201bd8e1d07e2bbbd8bcaaa5ce18e2", - "newlyBound": true, - "baselineSourceSha256": "4f2a93e0e00abb68277d09351a0a85c7fa201bd8e1d07e2bbbd8bcaaa5ce18e2" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQueryInputHandler.java", - "before": null, - "after": "46abd6c96d543f84b3884d1dafd4f41db9f6111e0edf9f770a8289f5604390a1", - "newlyBound": true, - "baselineSourceSha256": null - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/audit/AiAuditQueryService.java", - "before": "4067cc8685399b2b2bfb9e7b5eaddd10b906f63fccf286ef7e118622e4e80ea6", - "after": "01f316fb38aefd1e43f81773dab71576ff53ef37c4b8a9e844ae6d2556df3aca", - "newlyBound": false, - "baselineSourceSha256": "4067cc8685399b2b2bfb9e7b5eaddd10b906f63fccf286ef7e118622e4e80ea6" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchAccess.java", - "before": "639ceb2151b6668af77ff2f71ead2cd7699d76d45c17521e46a90af624286b52", - "after": "5f0e1de8995318226e0c8ae48acbd3a6e07b025e7fa068daa1bc5945e25c6d49", - "newlyBound": false, - "baselineSourceSha256": "639ceb2151b6668af77ff2f71ead2cd7699d76d45c17521e46a90af624286b52" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPlanResourceManager.java", - "before": "ef70bb6e029fdb446358ad81e9f791f14e892c28bda754b8ce479077fb85ff98", - "after": "b81b7e746d7557bd740b164123bd7584cf399b8b5a2bd57e258535392fe67b3d", - "newlyBound": false, - "baselineSourceSha256": "ef70bb6e029fdb446358ad81e9f791f14e892c28bda754b8ce479077fb85ff98" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchPlanService.java", - "before": "77b8f8b2b4ade110064ba0a874db04c1d5adbfe9df68655b8760c395270a05e3", - "after": "119c0347b3e6b984a76e1250fb2d2fee79337b77b13ed9dd87d888518efa818a", - "newlyBound": false, - "baselineSourceSha256": "77b8f8b2b4ade110064ba0a874db04c1d5adbfe9df68655b8760c395270a05e3" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanResourceManager.java", - "before": "37da81bdccdb528c1d7f1b18217d3896cabd0ad601e6a3809fd50913b6613050", - "after": "17ba569ba4f5265d7d3a8e50cc3ce2d21d220232c354e169be511b74ce212b17", - "newlyBound": false, - "baselineSourceSha256": "37da81bdccdb528c1d7f1b18217d3896cabd0ad601e6a3809fd50913b6613050" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangePlanService.java", - "before": "1d52b18a6b3efc5f86b30e52cb1ab57bb27f788e28703a4e7864d473dd7aa071", - "after": "1b920af86f0294b1c1e1ee44f4a9b7dc9bf7eac9e269298a1007c8ff235e6d45", - "newlyBound": false, - "baselineSourceSha256": "1d52b18a6b3efc5f86b30e52cb1ab57bb27f788e28703a4e7864d473dd7aa071" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/upgrade/AiServiceUpgradePlanInputHandler.java", - "before": null, - "after": "a38c9fece7444a5fd5385b48f9b9ca2997e8218c82c91096473115cc87ee69aa", - "newlyBound": true, - "baselineSourceSha256": null - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/upgrade/AiServiceUpgradePlanResourceManager.java", - "before": "51ac797f47ba68e52d360c6c53bb3aa143e33a637286deca9636f5d55559f1a8", - "after": "30cb1cdae0766c0f0a6c7f3f4c27187ca0bd565002bda4e311368e420e88d9a7", - "newlyBound": false, - "baselineSourceSha256": "51ac797f47ba68e52d360c6c53bb3aa143e33a637286deca9636f5d55559f1a8" - }, - { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/upgrade/AiServiceUpgradePlanService.java", - "before": null, - "after": "7398ac81e4287ee2e950d2b86b8ce55fd574d8af40831044553514e729d8204d", - "newlyBound": true, - "baselineSourceSha256": "12782760bbd8e600c06876006e39ff9e7f3de818ffb8e39a5e294f9484579a8a" - }, - { - "path": "code/iaas/service-discovery/api/src/main/java/io/cattle/platform/servicediscovery/api/filter/ServiceUpgradeValidationFilter.java", - "before": "27cea9ff5e7efc030de24d0095669fa5812a7931d64bcdbf8dfefb8888d7db36", - "after": "1adcf76557b3392161a46393d795b67a0ccc781a49d544fa8672aafe49475a63", - "newlyBound": false, - "baselineSourceSha256": "27cea9ff5e7efc030de24d0095669fa5812a7931d64bcdbf8dfefb8888d7db36" - }, - { - "path": "code/iaas/service-discovery/api/src/main/java/io/cattle/platform/servicediscovery/api/service/ServiceUpgradeValidation.java", - "before": null, - "after": "ffcf91e17f0aaffe821acf297d1e125768a5332c062c1bf5c435114035255cf1", - "newlyBound": true, - "baselineSourceSha256": null - }, - { - "path": "code/packaging/app-config/src/main/java/io/cattle/platform/app/IaasApiConfig.java", - "before": "59b633a3f6614f811b5f14b0eeeeb1f99683d319a2c28bea2093f48a33a53130", - "after": "fa64b48420abe59930c464283a773d2dfcccbaeea152fdf1a997d8dcae184e9a", - "newlyBound": false, - "baselineSourceSha256": "59b633a3f6614f811b5f14b0eeeeb1f99683d319a2c28bea2093f48a33a53130" - }, - { - "path": "resources/content/schema/admin/admin-auth.json", - "before": "f713ba64c53fb498b2cbe7f96b5c794ed35d093a74a78cafcffe3f19b59ef5df", - "after": "0282ac1900b37648214fc48dce394e00c1b22cc27340e08612d5e5e81ca66f64", - "newlyBound": false, - "baselineSourceSha256": "f713ba64c53fb498b2cbe7f96b5c794ed35d093a74a78cafcffe3f19b59ef5df" - }, - { - "path": "resources/content/schema/base/aiServiceUpgradePlan.json", - "before": "025cd4a0b044cda9f2500a79a99b605c867f95e8f69d46997ed843b221d67cb6", - "after": "5285ad2caab0e05e28fed27299e5ad114e84c15820bba9a9cfbfc45a163b62d0", - "newlyBound": false, - "baselineSourceSha256": "025cd4a0b044cda9f2500a79a99b605c867f95e8f69d46997ed843b221d67cb6" - }, - { - "path": "resources/content/schema/project/project-auth.json", - "before": "ce1ebde019bfd57d6ddd5c2b77d119a76e1df38bf887371e765478c3d96388cf", - "after": "8ba8e18dca27a9cc65208c49a5ab72f3ff3d4d4353ae6b8d6891a2f913a76f09", - "newlyBound": false, - "baselineSourceSha256": "ce1ebde019bfd57d6ddd5c2b77d119a76e1df38bf887371e765478c3d96388cf" - }, - { - "path": "resources/content/schema/user/user-auth.json", - "before": "66a82fa448806fb826ecd7a11bc9dc6cc9598e7a221d63191113457fd3376091", - "after": "4f54ea9c4b8b2d7d7e849e17a73f33d7262f2519e8263e28842ee7eaec414835", - "newlyBound": false, - "baselineSourceSha256": "66a82fa448806fb826ecd7a11bc9dc6cc9598e7a221d63191113457fd3376091" - } - ], - "roleFieldDelta": [ - { - "path": "resources/content/schema/admin/admin-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.startFirst", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/admin/admin-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.batchSize", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/admin/admin-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/admin/admin-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", - "before": null, - "after": "r" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiExternalServiceChange.java", + "before": "d9497a9c37842c09e833d434e5f361585f721a72eff9976c5b66902181f392e5", + "after": "4475ebc7215960f69ebaf5c5c925a3c2f4b933975efb9205aba16f80d30eaf47" }, { - "path": "resources/content/schema/project/project-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.startFirst", - "before": null, - "after": "cr" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDescriptor.java", + "before": "c60650a74476af5faadd8cc76bcab4d073fd294dfac28d8dc176c07daeb7d4dc", + "after": "8b81eaa0446c07c786e588ae8299456bc3c25dca90cf31810c29d1ca5a838e35" }, { - "path": "resources/content/schema/project/project-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.batchSize", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/project/project-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/project/project-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", - "before": null, - "after": "r" - }, - { - "path": "resources/content/schema/user/user-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.startFirst", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/user/user-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.batchSize", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/user/user-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/user/user-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", - "before": null, - "after": "r" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDomain.java", + "before": "fc2245d42e31f3426fef91d68bbe8039f67f50b0a47b9e60cd003c83d1776ad0", + "after": "331c7fa5eae1f60d4f33e3f3767c546d684042be6156a756ab60c627feef443a" } ], + "roleFieldDelta": [], "authorizationRationale": { - "operation": "1396 exact tuples and each semantic/registered/unsupported/human-only disposition unchanged.", - "strategy": "Only existing upgrade-plan roles accept three optional scalar fields; dispatch still uses the original authorized native manager. No target or scope grant is added.", - "preflight": "Existing native filter implements the shared read-only interface. Native strategy invariants, including retain-IP/start-first, and the same port/volume rules run at preview/confirmation/apply; native batch normalization and original validation errors remain unchanged, including their canonical DENY reason.", - "audit": "Exact typed audit collection only; a sticky boolean retains the original closed-field rejection, and the existing owner audits ERROR without invoking its runner. No raw payload is retained.", - "acceptance": "Source extraction does not establish artifact, role matrix, HTTP/UI or asynchronous runtime acceptance.", - "nativeActionOperandLookup": "Native Catalog-launch, resource-change and upgrade action operands use only exact framework request markers and authorized read snapshots. No prefetch observation writes or retained plan/credential row locks precede the action application lock. Ordinary GET observation and final action owner, role, Key revision, source/snapshot, CAS and one-claim checks remain; no timeout, retry, schema or grant expansion. New upgrade plans bind the complete strategy in their private target snapshot so older engines reject them before claim; genuine legacy image-only plans keep classic snapshots and original defaults." + "externalServiceCreate": "Existing parent/owner/current role/Key/revision, native schema and single durable claim boundaries remain; native cr field only, no update or global grant." } }, - "schemas": [ - "resources/content/schema/base/aiServiceDescriptionUpdate.json", - "resources/content/schema/base/aiServiceUpgradePlan.json", - "resources/content/schema/base/aiToolCallEvent.json", - "resources/content/schema/base/aiResourceView.json", - "resources/content/schema/base/aiResourceChangePlan.json", - "resources/content/schema/base/processPool.json", - "resources/content/schema/base/aiCatalogMetadataView.json", - "resources/content/schema/base/aiCatalogStackLaunchOptions.json", - "resources/content/schema/base/aiCatalogStackLaunchPlan.json", - "resources/content/schema/base/aiCatalogStackLaunchInputs.json", - "resources/content/schema/base/aiAuditQuery.json", - "resources/content/schema/base/aiAuditSourcePageInput.json" - ], - "addedTuples": [], - "changedTuples": [], "sourceInputChanges": [ { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiExternalServiceChange.java", - "before": "d9497a9c37842c09e833d434e5f361585f721a72eff9976c5b66902181f392e5", - "after": "4475ebc7215960f69ebaf5c5c925a3c2f4b933975efb9205aba16f80d30eaf47" + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiResourceViewService.java", + "before": "54f9aeaeecbf135e34210417f5cf7ec128a90e05b1971fc351ed4bdd76bf8585", + "after": "19d91fa89474c9c9604ff7a688afd9a36e6d75fd313667f16ef5550efedc050b" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDescriptor.java", - "before": "c60650a74476af5faadd8cc76bcab4d073fd294dfac28d8dc176c07daeb7d4dc", - "after": "8b81eaa0446c07c786e588ae8299456bc3c25dca90cf31810c29d1ca5a838e35" + "path": "code/iaas/model/src/main/java/io/cattle/platform/core/dao/VolumeDao.java", + "before": null, + "after": "8fbeb7ef1b63fa000d1788e2603d39de5e6e7dd83eec19df126bcb84510d3823" }, { - "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/change/AiResourceChangeDomain.java", - "before": "fc2245d42e31f3426fef91d68bbe8039f67f50b0a47b9e60cd003c83d1776ad0", - "after": "331c7fa5eae1f60d4f33e3f3767c546d684042be6156a756ab60c627feef443a" + "path": "code/iaas/model/src/main/java/io/cattle/platform/core/dao/impl/VolumeDaoImpl.java", + "before": null, + "after": "b0a41797307b7a02d44ad5ac08f00bad3fa21fb78143825ac4a01774a8ddcfe6" } - ], - "roleFieldDelta": [], - "authorizationRationale": { - "externalServiceCreate": "Existing parent/owner/current role/Key/revision, native schema and single durable claim boundaries remain; native cr field only, no update or global grant." - } + ] }, "tuples": [ ["account","collection","GET","","","read"], diff --git a/scripts/api-key-operation-inventory.json b/scripts/api-key-operation-inventory.json index 68ea2d3c51..af029e732b 100644 --- a/scripts/api-key-operation-inventory.json +++ b/scripts/api-key-operation-inventory.json @@ -220,18 +220,17 @@ "defaultProcesses": "ebf41ab873c349656c307511712674e0db434a9c4986e08d03ec35d92bdcd6a7" }, "currentSourceReview": { - "version": "unreleased-368-external-service-create-tcp-healthcheck", + "version": "unreleased-369-volume-usage-safe-read", "status": "SOURCE_REEXTRACTED_NOT_ARTIFACT_OR_RUNTIME_ACCEPTANCE", - "baseCommit": "8678dec7dd261c2f2b68f329f0722d8edc91ac1f", - "functionalSourceCommit": "2bd0ed5abffd3413422916b1df1aeaecb86fcb6a", + "baseCommit": "f466d3e514cc08f1d826299826b0b5db27df5d2f", "sourceCandidate": "WORKTREE_NOT_COMMITTED", "producerCommit": "NOT_ASSIGNED_DURING_SOURCE_REVIEW", "contract": "scripts/api-key-operation-contract.json", - "contractSha256": "0fb84661147a50f27e51a8a9501ac52fb0d3cabac02e790d6522dfe8c556e5dd", + "contractSha256": "99aba456727ef358339aa9456aa711e36aa9d72448cf10886a665892b1e2d048", "sourceInputs": { "algorithm": "c03-source-inputs-v1", - "count": 447, - "sha256": "da122b39e8ffac069b78d60c7234ff62cbb1995028efa835a7f717f8d02dee4c", + "count": 449, + "sha256": "5bbfd304067c39be44f7415ed00e654e2386ef8827f618a2f13ef6ed1c7562a3", "anchors": [ "AbstractSchemaFactory.java", "AiAliasServiceChange.java", @@ -328,6 +327,8 @@ "ServiceValidationFilter.java", "TokenAuthLookup.java", "TransformInspect.java", + "VolumeDao.java", + "VolumeDaoImpl.java", "VolumePreflightInputs.java", "VolumePreflightService.java" ], @@ -350,17 +351,18 @@ "roleFieldDelta": [], "historicalInventoryPreserved": true, "previousReview": { - "version": "unreleased-367-service-upgrade-strategy-audit-preview-native-action-lock-order-and-rollback-fence", - "status": "SOURCE_REEXTRACTED_NOT_SIGNED_NOT_RUNTIME_ACCEPTANCE", - "baseCommit": "c8cd1f8218d29e034c2569af1e0e8530c305ce50", + "version": "unreleased-368-external-service-create-tcp-healthcheck", + "status": "SOURCE_REEXTRACTED_NOT_ARTIFACT_OR_RUNTIME_ACCEPTANCE", + "baseCommit": "8678dec7dd261c2f2b68f329f0722d8edc91ac1f", + "functionalSourceCommit": "2bd0ed5abffd3413422916b1df1aeaecb86fcb6a", "sourceCandidate": "WORKTREE_NOT_COMMITTED", "producerCommit": "NOT_ASSIGNED_DURING_SOURCE_REVIEW", "contract": "scripts/api-key-operation-contract.json", - "contractSha256": "35b2b2447c0f07205b806ff7304aacb4a90ecface2558701dbde8725a56c50c8", + "contractSha256": "0fb84661147a50f27e51a8a9501ac52fb0d3cabac02e790d6522dfe8c556e5dd", "sourceInputs": { "algorithm": "c03-source-inputs-v1", "count": 447, - "sha256": "66a5ce2ee5f4277993c03de0f72a08dd828ec65e4c447430248c1b093583ab59", + "sha256": "da122b39e8ffac069b78d60c7234ff62cbb1995028efa835a7f717f8d02dee4c", "anchors": [ "AbstractSchemaFactory.java", "AiAliasServiceChange.java", @@ -476,96 +478,25 @@ "addedTuples": [], "removedTuples": [], "changedTuples": [], - "roleFieldDelta": [ - { - "path": "resources/content/schema/admin/admin-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.startFirst", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/admin/admin-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.batchSize", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/admin/admin-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/admin/admin-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", - "before": null, - "after": "r" - }, - { - "path": "resources/content/schema/project/project-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.startFirst", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/project/project-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.batchSize", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/project/project-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/project/project-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", - "before": null, - "after": "r" - }, - { - "path": "resources/content/schema/user/user-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.startFirst", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/user/user-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.batchSize", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/user/user-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", - "before": null, - "after": "cr" - }, - { - "path": "resources/content/schema/user/user-auth.json", - "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", - "before": null, - "after": "r" - } - ], + "roleFieldDelta": [], "historicalInventoryPreserved": true, "previousReview": { - "version": "unreleased-366-service-create-native-ports-healthcheck-and-catalog-projection", + "version": "unreleased-367-service-upgrade-strategy-audit-preview-native-action-lock-order-and-rollback-fence", "status": "SOURCE_REEXTRACTED_NOT_SIGNED_NOT_RUNTIME_ACCEPTANCE", - "baseCommit": "259ef59e8110fab71488d5dbd8c9affda4279217", - "sourceCandidate": "9efe87becb752287072e2257c949680fed75282d", + "baseCommit": "c8cd1f8218d29e034c2569af1e0e8530c305ce50", + "sourceCandidate": "WORKTREE_NOT_COMMITTED", + "producerCommit": "NOT_ASSIGNED_DURING_SOURCE_REVIEW", "contract": "scripts/api-key-operation-contract.json", - "contractSha256": "8af458ac13a30c611fde008992297ad77b6fb40e237d615b7397e74e4302c820", + "contractSha256": "35b2b2447c0f07205b806ff7304aacb4a90ecface2558701dbde8725a56c50c8", "sourceInputs": { "algorithm": "c03-source-inputs-v1", - "count": 441, - "sha256": "7ce17c8b05ccfba961414808148d8638bf54a9ad3bbc7de00facfcba4b26ac39", + "count": 447, + "sha256": "66a5ce2ee5f4277993c03de0f72a08dd828ec65e4c447430248c1b093583ab59", "anchors": [ "AbstractSchemaFactory.java", "AiAliasServiceChange.java", "AiAuditQuery.java", + "AiAuditQueryInputHandler.java", "AiAuditQueryResourceManager.java", "AiAuditQueryRunner.java", "AiAuditQueryService.java", @@ -609,6 +540,8 @@ "AiResourceViewResourceManager.java", "AiResourceViewService.java", "AiServiceCreateChange.java", + "AiServiceUpgradePlanInputHandler.java", + "AiServiceUpgradePlanService.java", "ApiAuditPayload.java", "ApiAuthenticator.java", "ApiCookieAuthentication.java", @@ -634,6 +567,7 @@ "FileSchemaFactory.java", "GenericWhitelistedProxy.java", "IaasApiConfig.java", + "InServiceUpgradeStrategy.java", "NotWritablePostProcessor.java", "PortBindingAddress.java", "PortPreflightInputs.java", @@ -648,9 +582,14 @@ "ServiceCreate.java", "ServiceCreateValidation.java", "ServiceDiscoveryServiceImpl.java", + "ServiceUpgradeStrategy.java", + "ServiceUpgradeValidation.java", + "ServiceUpgradeValidationFilter.java", "ServiceValidationFilter.java", "TokenAuthLookup.java", - "TransformInspect.java" + "TransformInspect.java", + "VolumePreflightInputs.java", + "VolumePreflightService.java" ], "markers": [ "@Type", @@ -668,68 +607,92 @@ "addedTuples": [], "removedTuples": [], "changedTuples": [], - "roleProjectionDelta": [ + "roleFieldDelta": [ + { + "path": "resources/content/schema/admin/admin-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.startFirst", + "before": null, + "after": "cr" + }, { "path": "resources/content/schema/admin/admin-auth.json", - "pointer": "/authorize/aiResourceChangePlan.executionResult", + "pointer": "/authorize/aiServiceUpgradePlan.batchSize", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/admin/admin-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/admin/admin-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", "before": null, "after": "r" }, { "path": "resources/content/schema/project/project-auth.json", - "pointer": "/authorize/aiResourceChangePlan.executionResult", + "pointer": "/authorize/aiServiceUpgradePlan.startFirst", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/project/project-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.batchSize", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/project/project-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/project/project-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", "before": null, "after": "r" }, { "path": "resources/content/schema/user/user-auth.json", - "pointer": "/authorize/aiResourceChangePlan.executionResult", + "pointer": "/authorize/aiServiceUpgradePlan.startFirst", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/user/user-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.batchSize", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/user/user-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.intervalMillis", + "before": null, + "after": "cr" + }, + { + "path": "resources/content/schema/user/user-auth.json", + "pointer": "/authorize/aiServiceUpgradePlan.upgradeStrategy", "before": null, "after": "r" } ], - "materializerDynamicProjection": { - "source": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchMaterializer.java", - "rootCause": "DockerTransformer stores imageUuid/environment/ports/logConfig in InstanceRecord data.fields; the five-argument WrappedResource constructor did not receive that dynamic value map, so the real role-schema projection omitted required business values.", - "fix": "Pass a fresh LinkedHashMap copy of DataUtils.getFields(instance) to the seven-argument WrappedResource constructor. Keep the existing current-role SchemaFactory, ID formatter, POST and createResponse=false behavior.", - "preservedBusinessValues": [ - "native docker imageUuid", - "environment exact scalar including embedded equals", - "fixed native ports", - "logConfig driver/config", - "bean-backed service name" - ], - "visibilityBoundary": "Current native role schema remains authoritative. Hidden environment, read-on-create-only ports/logConfig and unlisted dynamic fields remain absent; no role or Key authority expansion, raw bypass or new environment-input channel.", - "focusedTests": { - "newMethods": [ - "dynamicProjectionKeepsRestrictedSchemaAndNonCreateResponseRules", - "realTransformerDynamicFieldsReachNativeRoleSchemaProjection" - ], - "existingAffectedMethods": [ - "preparedGraphSeparatesNativeMutationFromAuthorizedPublicReferenceIds" - ], - "tests": 3, - "failures": 0, - "errors": 0, - "skipped": 0, - "evidenceFile": "engine366-materializer-dynamic-fields-focused-20261102.json", - "evidenceSha256": "24ea39c3caf6f6664735e67308246db34a07c59f384cccea48d9e2b171cbd35a", - "usesRealDockerTransformerAndNativeSchemas": true - }, - "runtimeAcceptance": "PENDING_MATCHING_ARTIFACT_AND_NATIVE_QA; no live pass claimed" - }, "historicalInventoryPreserved": true, - "producerCommit": "NOT_ASSIGNED_UNSIGNED_C03_REVIEW", "previousReview": { - "version": "unreleased-365-catalog-private-native-wire-fix", + "version": "unreleased-366-service-create-native-ports-healthcheck-and-catalog-projection", "status": "SOURCE_REEXTRACTED_NOT_SIGNED_NOT_RUNTIME_ACCEPTANCE", - "baseCommit": "aae91b38e1448ee4739cd4d361480e3fe633d925", + "baseCommit": "259ef59e8110fab71488d5dbd8c9affda4279217", + "sourceCandidate": "9efe87becb752287072e2257c949680fed75282d", "contract": "scripts/api-key-operation-contract.json", - "contractSha256": "fe3148ca74f9373fddc617be7ee518ac4d3618e38eed4038c227cb440c6347f1", + "contractSha256": "8af458ac13a30c611fde008992297ad77b6fb40e237d615b7397e74e4302c820", "sourceInputs": { "algorithm": "c03-source-inputs-v1", - "count": 432, - "sha256": "fdf53022efdab0e56edb292da037216be051643770565c090424124be8b115ea", + "count": 441, + "sha256": "7ce17c8b05ccfba961414808148d8638bf54a9ad3bbc7de00facfcba4b26ac39", "anchors": [ "AbstractSchemaFactory.java", "AiAliasServiceChange.java", @@ -776,6 +739,7 @@ "AiResourceChangeProcessObserver.java", "AiResourceViewResourceManager.java", "AiResourceViewService.java", + "AiServiceCreateChange.java", "ApiAuditPayload.java", "ApiAuthenticator.java", "ApiCookieAuthentication.java", @@ -802,12 +766,20 @@ "GenericWhitelistedProxy.java", "IaasApiConfig.java", "NotWritablePostProcessor.java", + "PortBindingAddress.java", + "PortPreflightInputs.java", + "PortPreflightService.java", + "PortSpec.java", "ProcessAuthorization.java", "ProcessEventDecorator.java", "RequestReRouterHandler.java", "ResourceManagerRequestHandler.java", "SchemaFactoryImpl.java", "ServiceConsumeMapDaoImpl.java", + "ServiceCreate.java", + "ServiceCreateValidation.java", + "ServiceDiscoveryServiceImpl.java", + "ServiceValidationFilter.java", "TokenAuthLookup.java", "TransformInspect.java" ], @@ -827,18 +799,68 @@ "addedTuples": [], "removedTuples": [], "changedTuples": [], + "roleProjectionDelta": [ + { + "path": "resources/content/schema/admin/admin-auth.json", + "pointer": "/authorize/aiResourceChangePlan.executionResult", + "before": null, + "after": "r" + }, + { + "path": "resources/content/schema/project/project-auth.json", + "pointer": "/authorize/aiResourceChangePlan.executionResult", + "before": null, + "after": "r" + }, + { + "path": "resources/content/schema/user/user-auth.json", + "pointer": "/authorize/aiResourceChangePlan.executionResult", + "before": null, + "after": "r" + } + ], + "materializerDynamicProjection": { + "source": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/catalog/AiCatalogLaunchMaterializer.java", + "rootCause": "DockerTransformer stores imageUuid/environment/ports/logConfig in InstanceRecord data.fields; the five-argument WrappedResource constructor did not receive that dynamic value map, so the real role-schema projection omitted required business values.", + "fix": "Pass a fresh LinkedHashMap copy of DataUtils.getFields(instance) to the seven-argument WrappedResource constructor. Keep the existing current-role SchemaFactory, ID formatter, POST and createResponse=false behavior.", + "preservedBusinessValues": [ + "native docker imageUuid", + "environment exact scalar including embedded equals", + "fixed native ports", + "logConfig driver/config", + "bean-backed service name" + ], + "visibilityBoundary": "Current native role schema remains authoritative. Hidden environment, read-on-create-only ports/logConfig and unlisted dynamic fields remain absent; no role or Key authority expansion, raw bypass or new environment-input channel.", + "focusedTests": { + "newMethods": [ + "dynamicProjectionKeepsRestrictedSchemaAndNonCreateResponseRules", + "realTransformerDynamicFieldsReachNativeRoleSchemaProjection" + ], + "existingAffectedMethods": [ + "preparedGraphSeparatesNativeMutationFromAuthorizedPublicReferenceIds" + ], + "tests": 3, + "failures": 0, + "errors": 0, + "skipped": 0, + "evidenceFile": "engine366-materializer-dynamic-fields-focused-20261102.json", + "evidenceSha256": "24ea39c3caf6f6664735e67308246db34a07c59f384cccea48d9e2b171cbd35a", + "usesRealDockerTransformerAndNativeSchemas": true + }, + "runtimeAcceptance": "PENDING_MATCHING_ARTIFACT_AND_NATIVE_QA; no live pass claimed" + }, "historicalInventoryPreserved": true, - "producerCommit": "NOT_ASSIGNED_UNSIGNED_OVERLAY", + "producerCommit": "NOT_ASSIGNED_UNSIGNED_C03_REVIEW", "previousReview": { - "version": "unreleased-365-native-validation-cleanup-fixes", + "version": "unreleased-365-catalog-private-native-wire-fix", "status": "SOURCE_REEXTRACTED_NOT_SIGNED_NOT_RUNTIME_ACCEPTANCE", - "baseCommit": "a335cf8513d8ddb61d1e90f19a9a70769b8ede04", + "baseCommit": "aae91b38e1448ee4739cd4d361480e3fe633d925", "contract": "scripts/api-key-operation-contract.json", - "contractSha256": "a1b07004f7e6d40c91c60a7cf88bab15d99ea5602f5347333717027098946bcb", + "contractSha256": "fe3148ca74f9373fddc617be7ee518ac4d3618e38eed4038c227cb440c6347f1", "sourceInputs": { "algorithm": "c03-source-inputs-v1", "count": 432, - "sha256": "5a8f5d8159d22c989733c92568916e936915a7d5a81724e3f082af3b65523f43", + "sha256": "fdf53022efdab0e56edb292da037216be051643770565c090424124be8b115ea", "anchors": [ "AbstractSchemaFactory.java", "AiAliasServiceChange.java", @@ -937,17 +959,17 @@ "removedTuples": [], "changedTuples": [], "historicalInventoryPreserved": true, - "producerCommit": "NOT_ASSIGNED_UNSIGNED_WORKTREE", + "producerCommit": "NOT_ASSIGNED_UNSIGNED_OVERLAY", "previousReview": { - "version": "unreleased-364-native-lifecycle-fixes", + "version": "unreleased-365-native-validation-cleanup-fixes", "status": "SOURCE_REEXTRACTED_NOT_SIGNED_NOT_RUNTIME_ACCEPTANCE", - "baseCommit": "fcc23550a937f473b92e3adf5014bc3fa1096aef", + "baseCommit": "a335cf8513d8ddb61d1e90f19a9a70769b8ede04", "contract": "scripts/api-key-operation-contract.json", - "contractSha256": "0456695780b3b53bdbd034dd640dc21776b0242b5828f2aff56ab230eb722c6a", + "contractSha256": "a1b07004f7e6d40c91c60a7cf88bab15d99ea5602f5347333717027098946bcb", "sourceInputs": { "algorithm": "c03-source-inputs-v1", "count": 432, - "sha256": "169fe350bed9358c2d9cbdac24f75c8636258325f2a92305507ad06e79c993e1", + "sha256": "5a8f5d8159d22c989733c92568916e936915a7d5a81724e3f082af3b65523f43", "anchors": [ "AbstractSchemaFactory.java", "AiAliasServiceChange.java", @@ -1048,15 +1070,15 @@ "historicalInventoryPreserved": true, "producerCommit": "NOT_ASSIGNED_UNSIGNED_WORKTREE", "previousReview": { - "version": "unreleased-363-external-review-before", + "version": "unreleased-364-native-lifecycle-fixes", "status": "SOURCE_REEXTRACTED_NOT_SIGNED_NOT_RUNTIME_ACCEPTANCE", - "baseCommit": "4c69935fa8177e9f9ae675cdd00702a45be72f33", + "baseCommit": "fcc23550a937f473b92e3adf5014bc3fa1096aef", "contract": "scripts/api-key-operation-contract.json", - "contractSha256": "1d0f71fa4913f3725b076ad0675f804e6297af9c7ef4a1036fd4acabd10da2c7", + "contractSha256": "0456695780b3b53bdbd034dd640dc21776b0242b5828f2aff56ab230eb722c6a", "sourceInputs": { "algorithm": "c03-source-inputs-v1", - "count": 431, - "sha256": "5bd56f773b6d57827ee04cfb5fb51f3e9ff95969a152edbbbff40abf3bb338fc", + "count": 432, + "sha256": "169fe350bed9358c2d9cbdac24f75c8636258325f2a92305507ad06e79c993e1", "anchors": [ "AbstractSchemaFactory.java", "AiAliasServiceChange.java", @@ -1123,6 +1145,7 @@ "EngineContext.java", "EventBasedProcessHandler.java", "EventDiagnostics.java", + "ExternalDeploymentUnitInstance.java", "ExternalDynamicExtensionHandler.java", "FileSchemaFactory.java", "GenericWhitelistedProxy.java", @@ -1156,15 +1179,15 @@ "historicalInventoryPreserved": true, "producerCommit": "NOT_ASSIGNED_UNSIGNED_WORKTREE", "previousReview": { - "version": "unreleased-362-service-index-cleanup", + "version": "unreleased-363-external-review-before", "status": "SOURCE_REEXTRACTED_NOT_SIGNED_NOT_RUNTIME_ACCEPTANCE", - "baseCommit": "06d5bf0dac57bf3be63fa7ce868c8d5fec2508ce", + "baseCommit": "4c69935fa8177e9f9ae675cdd00702a45be72f33", "contract": "scripts/api-key-operation-contract.json", - "contractSha256": "0c28b642db338e44a8fac584f5502d77b18f591c31e5a28ea744afc850a114fd", + "contractSha256": "1d0f71fa4913f3725b076ad0675f804e6297af9c7ef4a1036fd4acabd10da2c7", "sourceInputs": { "algorithm": "c03-source-inputs-v1", "count": 431, - "sha256": "28e69f831778a7355fbcdbcb66a6af18467a15404861492fb4baa57ca64c5048", + "sha256": "5bd56f773b6d57827ee04cfb5fb51f3e9ff95969a152edbbbff40abf3bb338fc", "anchors": [ "AbstractSchemaFactory.java", "AiAliasServiceChange.java", @@ -1264,14 +1287,15 @@ "historicalInventoryPreserved": true, "producerCommit": "NOT_ASSIGNED_UNSIGNED_WORKTREE", "previousReview": { + "version": "unreleased-362-service-index-cleanup", "status": "SOURCE_REEXTRACTED_NOT_SIGNED_NOT_RUNTIME_ACCEPTANCE", - "baseCommit": "48c052d569364e962938f1d2b6442330456113c3", + "baseCommit": "06d5bf0dac57bf3be63fa7ce868c8d5fec2508ce", "contract": "scripts/api-key-operation-contract.json", - "contractSha256": "f7c76b5500654d6e05adf869c50d67d7d376e93119b5a93db933edd4c7d0c7b4", + "contractSha256": "0c28b642db338e44a8fac584f5502d77b18f591c31e5a28ea744afc850a114fd", "sourceInputs": { "algorithm": "c03-source-inputs-v1", "count": 431, - "sha256": "ef3f2b2d2fd8b8ec62e6231d8318a7bc9d69dfe6d6949588ca397373d8bb9308", + "sha256": "28e69f831778a7355fbcdbcb66a6af18467a15404861492fb4baa57ca64c5048", "anchors": [ "AbstractSchemaFactory.java", "AiAliasServiceChange.java", @@ -1369,35 +1393,145 @@ "removedTuples": [], "changedTuples": [], "historicalInventoryPreserved": true, - "producerCommit": "NOT_ASSIGNED_UNSIGNED_WORKTREE" + "producerCommit": "NOT_ASSIGNED_UNSIGNED_WORKTREE", + "previousReview": { + "status": "SOURCE_REEXTRACTED_NOT_SIGNED_NOT_RUNTIME_ACCEPTANCE", + "baseCommit": "48c052d569364e962938f1d2b6442330456113c3", + "contract": "scripts/api-key-operation-contract.json", + "contractSha256": "f7c76b5500654d6e05adf869c50d67d7d376e93119b5a93db933edd4c7d0c7b4", + "sourceInputs": { + "algorithm": "c03-source-inputs-v1", + "count": 431, + "sha256": "ef3f2b2d2fd8b8ec62e6231d8318a7bc9d69dfe6d6949588ca397373d8bb9308", + "anchors": [ + "AbstractSchemaFactory.java", + "AiAliasServiceChange.java", + "AiAuditQuery.java", + "AiAuditQueryResourceManager.java", + "AiAuditQueryRunner.java", + "AiAuditQueryService.java", + "AiAuditSourcePage.java", + "AiAuditSourcePageInput.java", + "AiCatalogLaunchAccess.java", + "AiCatalogLaunchAccessTest.java", + "AiCatalogLaunchBinding.java", + "AiCatalogLaunchBindingTest.java", + "AiCatalogLaunchDelegation.java", + "AiCatalogLaunchDelegationTest.java", + "AiCatalogLaunchGateway.java", + "AiCatalogLaunchGraph.java", + "AiCatalogLaunchHumanInputTest.java", + "AiCatalogLaunchInput.java", + "AiCatalogLaunchMaterializer.java", + "AiCatalogLaunchMaterializerTest.java", + "AiCatalogLaunchObservation.java", + "AiCatalogLaunchObservationTest.java", + "AiCatalogLaunchOptionsResourceManager.java", + "AiCatalogLaunchOptionsService.java", + "AiCatalogLaunchOptionsStore.java", + "AiCatalogLaunchOptionsStoreTest.java", + "AiCatalogLaunchOwnerContractTest.java", + "AiCatalogLaunchPlanResourceManager.java", + "AiCatalogLaunchPlanService.java", + "AiCatalogLaunchPlanStore.java", + "AiCatalogLaunchPlanStoreTest.java", + "AiCatalogLaunchPrivate.java", + "AiCatalogLaunchPrivateTest.java", + "AiCatalogLaunchProspectiveParentTest.java", + "AiCatalogLaunchResponseFilter.java", + "AiCatalogLaunchRunner.java", + "AiCatalogLaunchWorkflowTest.java", + "AiExternalServiceChange.java", + "AiResourceChangeDescriptor.java", + "AiResourceChangeDomain.java", + "AiResourceChangePlanService.java", + "AiResourceChangePlanStore.java", + "AiResourceChangeProcessObserver.java", + "AiResourceViewResourceManager.java", + "AiResourceViewService.java", + "ApiAuditPayload.java", + "ApiAuthenticator.java", + "ApiCookieAuthentication.java", + "ApiKeyAuditSink.java", + "ApiKeyAuthorizationService.java", + "ApiKeyOperations.java", + "ApiKeyProcessAuthorization.java", + "ApiKeyQueryScopes.java", + "ApiKeyTargetResolver.java", + "ApiServerConfig.java", + "AuditLogOutPutFilter.java", + "AuditServiceImpl.java", + "CatalogLaunchTransformAuthorization.java", + "DefaultAuthorizationProvider.java", + "DefaultObjectMetaDataManager.java", + "DefaultProcessInstanceImpl.java", + "DefaultProcessesParser.java", + "EngineContext.java", + "EventBasedProcessHandler.java", + "EventDiagnostics.java", + "ExternalDynamicExtensionHandler.java", + "FileSchemaFactory.java", + "GenericWhitelistedProxy.java", + "IaasApiConfig.java", + "NotWritablePostProcessor.java", + "ProcessAuthorization.java", + "ProcessEventDecorator.java", + "RequestReRouterHandler.java", + "ResourceManagerRequestHandler.java", + "SchemaFactoryImpl.java", + "ServiceConsumeMapDaoImpl.java", + "TokenAuthLookup.java", + "TransformInspect.java" + ], + "markers": [ + "@Type", + "@Actions", + " getLinkInternal(", + " getLink(", + " resourceActionInternal(", + " collectionActionInternal(", + " resourceAction(", + " collectionAction(" + ] + }, + "tupleCount": 1396, + "tupleSha256": "8f1c0fb378663b0b3d272efba2f211cb210eb6f17cb8035aefa33b56feeaf36a", + "addedTuples": [], + "removedTuples": [], + "changedTuples": [], + "historicalInventoryPreserved": true, + "producerCommit": "NOT_ASSIGNED_UNSIGNED_WORKTREE" + } } } } } - } + }, + "reviewManifest": "scripts/api-key-operation-review-0.183.366.json", + "reviewManifestSha256": "44e30398885ac2eee8af7aef8bcc576c2b3d90b347e30cef6ecc96469934f0c7" }, - "reviewManifest": "scripts/api-key-operation-review-0.183.366.json", - "reviewManifestSha256": "44e30398885ac2eee8af7aef8bcc576c2b3d90b347e30cef6ecc96469934f0c7" + "reviewManifest": "scripts/api-key-operation-review-0.183.367.json", + "reviewManifestSha256": "d4ecd4a95d4d541b5042f410aafcf64342c2d8900a899e93fedb7b640b395669", + "nativeActionOperandLockOrder": { + "owners": [ + "aiCatalogStackLaunchPlan", + "aiResourceChangePlan", + "aiServiceUpgradePlan" + ], + "rootCause": "Outer native API write transaction retained a prefetch row lock after application-lock release; concurrent receipt GET inverted lock order.", + "fix": "Native Catalog-launch, resource-change and upgrade action operands use only exact framework request markers and authorized read snapshots. No prefetch observation writes or retained plan/credential row locks precede the action application lock. Ordinary GET observation and final action owner, role, Key revision, source/snapshot, CAS and one-claim checks remain; no timeout, retry, schema or grant expansion. New upgrade plans bind the complete strategy in their private target snapshot so older engines reject them before claim; genuine legacy image-only plans keep classic snapshots and original defaults.", + "lockTimeoutChanges": 0, + "retryChanges": 0, + "removedLocks": 0, + "databaseChanges": 0, + "uiPollingCausalityClaimed": false, + "runtimeAcceptanceClaimed": false + } }, - "reviewManifest": "scripts/api-key-operation-review-0.183.367.json", - "reviewManifestSha256": "d4ecd4a95d4d541b5042f410aafcf64342c2d8900a899e93fedb7b640b395669", - "nativeActionOperandLockOrder": { - "owners": [ - "aiCatalogStackLaunchPlan", - "aiResourceChangePlan", - "aiServiceUpgradePlan" - ], - "rootCause": "Outer native API write transaction retained a prefetch row lock after application-lock release; concurrent receipt GET inverted lock order.", - "fix": "Native Catalog-launch, resource-change and upgrade action operands use only exact framework request markers and authorized read snapshots. No prefetch observation writes or retained plan/credential row locks precede the action application lock. Ordinary GET observation and final action owner, role, Key revision, source/snapshot, CAS and one-claim checks remain; no timeout, retry, schema or grant expansion. New upgrade plans bind the complete strategy in their private target snapshot so older engines reject them before claim; genuine legacy image-only plans keep classic snapshots and original defaults.", - "lockTimeoutChanges": 0, - "retryChanges": 0, - "removedLocks": 0, - "databaseChanges": 0, - "uiPollingCausalityClaimed": false, - "runtimeAcceptanceClaimed": false - } + "reviewManifest": "scripts/api-key-operation-review-0.183.368.json", + "reviewManifestSha256": "71c1ab8fe2080bfda7a52c9a8349754c0c67b48a9eb16b6181a42ce8a4528d15" }, - "reviewManifest": "scripts/api-key-operation-review-0.183.368.json", - "reviewManifestSha256": "71c1ab8fe2080bfda7a52c9a8349754c0c67b48a9eb16b6181a42ce8a4528d15" + "reviewManifest": "scripts/api-key-operation-review-0.183.369.json", + "reviewManifestSha256": "8adb6a02225e5806561146b83a34461eb6d640fddf5a0a8aa552d0ccf81d53c9" } } diff --git a/scripts/api-key-operation-review-0.183.369.json b/scripts/api-key-operation-review-0.183.369.json new file mode 100644 index 0000000000..c103d1063f --- /dev/null +++ b/scripts/api-key-operation-review-0.183.369.json @@ -0,0 +1,57 @@ +{ + "schemaVersion": 1, + "version": "0.183.369", + "scope": "SOURCE_ONLY_NOT_RUNTIME_ACCEPTANCE", + "reviewedBaseCommit": "f466d3e514cc08f1d826299826b0b5db27df5d2f", + "sourceInputs": { + "algorithm": "c03-source-inputs-v1", + "baseline": { + "count": 447, + "sha256": "da122b39e8ffac069b78d60c7234ff62cbb1995028efa835a7f717f8d02dee4c" + }, + "reviewed": { + "count": 449, + "sha256": "5bbfd304067c39be44f7415ed00e654e2386ef8827f618a2f13ef6ed1c7562a3" + }, + "addedAnchors": [ + "VolumeDao.java", + "VolumeDaoImpl.java" + ] + }, + "tupleReview": { + "baseline": 1396, + "candidate": 1396, + "added": 0, + "removed": 0, + "semanticChanges": 0, + "dispositionChanges": 0, + "sha256": "8f1c0fb378663b0b3d272efba2f211cb210eb6f17cb8035aefa33b56feeaf36a" + }, + "delta": [ + { + "path": "code/iaas/auth-logic/src/main/java/io/cattle/platform/iaas/api/auth/ai/view/AiResourceViewService.java", + "before": "54f9aeaeecbf135e34210417f5cf7ec128a90e05b1971fc351ed4bdd76bf8585", + "after": "19d91fa89474c9c9604ff7a688afd9a36e6d75fd313667f16ef5550efedc050b" + }, + { + "path": "code/iaas/model/src/main/java/io/cattle/platform/core/dao/VolumeDao.java", + "before": null, + "after": "8fbeb7ef1b63fa000d1788e2603d39de5e6e7dd83eec19df126bcb84510d3823" + }, + { + "path": "code/iaas/model/src/main/java/io/cattle/platform/core/dao/impl/VolumeDaoImpl.java", + "before": null, + "after": "b0a41797307b7a02d44ad5ac08f00bad3fa21fb78143825ac4a01774a8ddcfe6" + } + ], + "authorizationBoundary": "Volume detail adds a read-only bounded usage-reference projection through the existing typed resource view. Native SQL retrieves at most 51 relationships before materialization and exposes at most 50 authorized container targets. Current native object authorization and an exact attested Key query scope remain mandatory; unsupported scoped managers return unknown. Hidden targets create no synthetic API/audit entries. The selected Volume read retains canonical audit and direct hidden-resource requests retain DENY audit. Closed scalar fields reuse native data-field precedence and current-role schema wrapping, excluding transformed/create-only fields before access; parent names require a readable persisted Stack relationship and a fresh authorized Stack read. Completeness is always unknown; no total, hidden identity/count, host source path, write, grant or deletion-oracle change.", + "frozenV1SchemaFilesUnchanged": true, + "extractor": { + "constructionSha256": "078ffe48881469fe5eb3cb43a15fa41b480fe70e11bd5f63102ded6b35a6d076", + "parserSha256": "7cc8e70d9f3ea391eb74fef2490f4407aa47833c585b6729c62b3d9e5829ac2b", + "extractorSha256": "112d2ff723d88acbe7bb45ff48c9c9018feb93b08031a3e86f867030871477fc" + }, + "historicalProducerAndReviewChainsPreserved": true, + "artifactQualificationClaimed": false, + "runtimeAcceptanceClaimed": false +} diff --git a/scripts/build b/scripts/build index c8ab9d736a..c368694f2d 100755 --- a/scripts/build +++ b/scripts/build @@ -16,7 +16,7 @@ fi SOURCE_REVISION=${SOURCE_REVISION:-$(git rev-parse HEAD)} SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH:-$(git show -s --format=%ct HEAD)} -ENGINE_VERSION=${ENGINE_VERSION:-0.183.368} +ENGINE_VERSION=${ENGINE_VERSION:-0.183.369} case "$SOURCE_REVISION" in ''|*[!0-9a-f]*) diff --git a/scripts/check-cattle-jdk25-standalone b/scripts/check-cattle-jdk25-standalone index 9ce4b39bf4..4c3133d189 100755 --- a/scripts/check-cattle-jdk25-standalone +++ b/scripts/check-cattle-jdk25-standalone @@ -6,7 +6,7 @@ cd "$repo_root" java_cmd=${JAVA_CMD:-java} runner_image=${RC16_CATTLE_STANDALONE_JDK_IMAGE:-maven:3.9.16-eclipse-temurin-25@sha256:1b1fc6d0168ea616afd1c861d6f32ec37c9ec2ffe88a0351b3771dd4ad86b0d8} -expected_version=${EXPECTED_ENGINE_VERSION:-${ENGINE_VERSION:-0.183.368}} +expected_version=${EXPECTED_ENGINE_VERSION:-${ENGINE_VERSION:-0.183.369}} artifact=${RC16_CATTLE_STANDALONE_JAR:-dist/artifacts/cattle.jar} # Full-package invokes Maven directly, without scripts/build's final copy. diff --git a/scripts/check-pasturestack-source b/scripts/check-pasturestack-source index 6c6150f9a5..de25015dc1 100755 --- a/scripts/check-pasturestack-source +++ b/scripts/check-pasturestack-source @@ -51,7 +51,7 @@ fi project_version=$(sed -n 's/^[[:space:]]*\([^<]*\)<\/version>[[:space:]]*$/\1/p' code/meta-parent/pom.xml | head -n 1) [[ "$project_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || fail non_numeric_project_version -require_line code/meta-parent/pom.xml ' 0.183.368' +require_line code/meta-parent/pom.xml ' 0.183.369' require_line code/meta-parent/pom.xml ' 33.7.2-jre' require_line ubuntu-security-packages.lock 'libbrotli1=1.2.0-3ubuntu0.1' require_line ubuntu-security-packages.lock 'libpcre2-8-0=10.46-1ubuntu0.1' @@ -486,4 +486,4 @@ require_line README.md 'PastureStack is an independent community effort to prese require_line README.md 'Rancher 1.6 ecosystem. It is not affiliated with Rancher Labs or SUSE.' require_line ORIGIN.md '- Preserved upstream boundary: `82d154a53f4089fecfb9f320caad826bb4f6055f`' -printf 'PASTURESTACK_SOURCE_GATE_OK version=0.183.368 runtime_sources=github_release images=digest_pinned ubuntu=26.04 ubuntu_snapshot=20260826T000000Z jdk=25.0.5 go=1.27.3 curl=8.18.0-1ubuntu2.8 openssl=3.5.5-1ubuntu3.7 maven=3.9.16 patched_hazelcast=5.7.6 docker_cli=29.9.2 docker_host_29_8_0=exact credential_secret_capacity=mediumtext port_preflight=authoritative volume_preflight=runtime_resolution_aligned volume_preflight_project_schema=authorized volume_preflight_type_set=registered v1_hardware_schema=container-and-launchConfig network_driver_rollback=launch-config-restored stack_driver_rollback=child-launch-config-restored auth_token_session_binding=authorized-create-only auth_token_transport=bare-or-bearer-normalized auth_token_frozen_v1_schema=base-superadmin-token oidc_external_types=validated-before-mutation-owned-stable-account oidc_account_activation=sync-before-mfa oidc_v1_project_member_schema=core-options-merged-scoped oidc_identity_link_owner=explicit-and-verified legacy_token_link_repair=exact-match-only oidc_required_local_recovery=active-admin-only default_project=shared-idempotent-role-preserving,atomic-identity-set oidc_restricted_project_membership=stable-account-aware-required-allowlist-only mfa_policy_confirmation=actor-purpose-digest-single-use auth_config_proxy_identity=caller-platform-credential project_member_collection_acl=requested-project-checked-before-load project_template_v1_public=readonly-frozen-field-merged network_purge=retry-removing dev_artifact=forbidden\n' +printf 'PASTURESTACK_SOURCE_GATE_OK version=0.183.369 runtime_sources=github_release images=digest_pinned ubuntu=26.04 ubuntu_snapshot=20260826T000000Z jdk=25.0.5 go=1.27.3 curl=8.18.0-1ubuntu2.8 openssl=3.5.5-1ubuntu3.7 maven=3.9.16 patched_hazelcast=5.7.6 docker_cli=29.9.2 docker_host_29_8_0=exact credential_secret_capacity=mediumtext port_preflight=authoritative volume_preflight=runtime_resolution_aligned volume_preflight_project_schema=authorized volume_preflight_type_set=registered v1_hardware_schema=container-and-launchConfig network_driver_rollback=launch-config-restored stack_driver_rollback=child-launch-config-restored auth_token_session_binding=authorized-create-only auth_token_transport=bare-or-bearer-normalized auth_token_frozen_v1_schema=base-superadmin-token oidc_external_types=validated-before-mutation-owned-stable-account oidc_account_activation=sync-before-mfa oidc_v1_project_member_schema=core-options-merged-scoped oidc_identity_link_owner=explicit-and-verified legacy_token_link_repair=exact-match-only oidc_required_local_recovery=active-admin-only default_project=shared-idempotent-role-preserving,atomic-identity-set oidc_restricted_project_membership=stable-account-aware-required-allowlist-only mfa_policy_confirmation=actor-purpose-digest-single-use auth_config_proxy_identity=caller-platform-credential project_member_collection_acl=requested-project-checked-before-load project_template_v1_public=readonly-frozen-field-merged network_purge=retry-removing dev_artifact=forbidden\n' diff --git a/scripts/check-release-artifact b/scripts/check-release-artifact index c9e90f260d..4f31c5b1cc 100755 --- a/scripts/check-release-artifact +++ b/scripts/check-release-artifact @@ -4,7 +4,7 @@ set -euo pipefail cd "$(dirname "$0")/.." artifact=${1:-dist/artifacts/cattle.jar} -expected_version=${EXPECTED_ENGINE_VERSION:-0.183.368} +expected_version=${EXPECTED_ENGINE_VERSION:-0.183.369} test -f "$artifact" artifact=$(realpath "$artifact")