From 0d94f7d879d314235e582a7f4062914a27b82709 Mon Sep 17 00:00:00 2001
From: chen21019 <19357113+chen21019@users.noreply.github.com>
Date: Sat, 3 Oct 2026 14:50:25 +0800
Subject: [PATCH] fix(api): restrict create-only values to actual resource
creation
---
.github/workflows/security-release-gate.yml | 22 +++
COMPATIBILITY.md | 15 ++
README.md | 11 ++
code/framework/api-pub-sub-jetty/pom.xml | 2 +-
code/framework/api-pub-sub/pom.xml | 2 +-
code/framework/api/pom.xml | 2 +-
.../cattle/platform/api/utils/ApiUtils.java | 4 +-
.../api/schema/FileSchemaFactoryTest.java | 21 +++
.../api/utils/ApiUtilsCreateOnlyTest.java | 142 ++++++++++++++++++
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 +-
.../gdapi/model/impl/WrappedResource.java | 18 ++-
.../impl/AbstractBaseResourceManager.java | 2 +-
.../gdapi/response/JsonResponseWriter.java | 5 +-
.../gdapi/util/RequestUtils.java | 5 +
.../model/impl/CreateOnlyCallerTest.java | 131 ++++++++++++++++
.../impl/CreateOnlyWrappedResourceTest.java | 100 ++++++++++++
.../gdapi/util/RequestUtilsTest.java | 19 +++
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 +-
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 +-
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.333.md | 44 ++++++
pom.xml | 2 +-
resources/pom.xml | 2 +-
scripts/build | 2 +-
scripts/check-pasturestack-source | 4 +-
scripts/check-release-artifact | 2 +-
106 files changed, 628 insertions(+), 101 deletions(-)
create mode 100644 code/framework/api/src/test/java/io/cattle/platform/api/utils/ApiUtilsCreateOnlyTest.java
create mode 100644 code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/CreateOnlyCallerTest.java
create mode 100644 code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/CreateOnlyWrappedResourceTest.java
create mode 100644 docs/releases/orchestration-engine-0.183.333.md
diff --git a/.github/workflows/security-release-gate.yml b/.github/workflows/security-release-gate.yml
index 3d909f1603..1eb42bcd48 100644
--- a/.github/workflows/security-release-gate.yml
+++ b/.github/workflows/security-release-gate.yml
@@ -57,8 +57,30 @@ jobs:
import xml.etree.ElementTree as ET
required = {
+ 'io.github.ibuildthecloud.gdapi.model.impl.CreateOnlyWrappedResourceTest': {
+ 'trueCreationRetainsTheFirstSecretInBothApiVersions',
+ 'postActionsCannotRevealCreateOnlyValues',
+ 'readUpdateDeleteAndUnknownMethodsStillRedact',
+ 'rolesWithoutCreateOnlyRestrictionKeepTheirExistingReadContract',
+ 'methodOnlyLegacyConstructorsFailClosedInsteadOfGuessingCreation',
+ 'priorityFieldsCannotBypassTheCreateOnlyBoundary',
+ },
+ 'io.github.ibuildthecloud.gdapi.model.impl.CreateOnlyCallerTest': {
+ 'managerConstructResourceUsesTheRequestActionNotOnlyPostMethod',
+ 'responseWriterCreateResourceUsesTheActualContextRequest',
+ },
+ 'io.cattle.platform.api.utils.ApiUtilsCreateOnlyTest': {
+ 'trueCreateAllowsBeanAndAdditionalFieldValuesInBothRoots',
+ 'postActionsRedactBothValueSourcesWithoutRedactingUnflaggedNames',
+ 'nullRequestFailsClosedForBothValueSources',
+ 'readUpdateAndDeleteCannotUseTheCreateException',
+ },
+ 'io.github.ibuildthecloud.gdapi.util.RequestUtilsTest': {
+ 'creationRequiresPostAndAbsentActionNotAStatusCode',
+ },
'io.cattle.platform.api.schema.FileSchemaFactoryTest': {
'restoresOnlyNativeReadFieldInPackagedFrozenVolumeRoleSchemas',
+ 'preservesCreateOnlyApiKeyFlagInThePackagedFrozenV1UserSchema',
},
'io.cattle.platform.schema.processor.VolumeNativeSchemaAuthorizationTest': {
'currentRoleOverlaysExposeNativeClassificationWithoutGrantingMutation',
diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md
index ad28164969..66feb3ad2f 100644
--- a/COMPATIBILITY.md
+++ b/COMPATIBILITY.md
@@ -4,6 +4,21 @@ The migration preserves established `io.cattle.*` Java packages, Maven coordinat
New operator-facing names use PastureStack and `PASTURESTACK_*`. Compatibility identifiers must be changed only with an explicit data migration, a dual-read or dual-write transition, a rollback plan, and cross-repository verification.
+## Read-on-create-only responses
+
+Candidate `0.183.333` applies the existing schema `o` flag only to real resource
+creation (`POST` with no action), matching resource-manager dispatch. API Key
+deactivate, activate, remove and other POST actions must not return a stored
+create-only value. Existing null-redaction representation, ordinary readable
+fields, create-time first-secret delivery, v1 frozen schemas and v2 overlays are
+preserved. All three response wrappers share one decision. Legacy constructors
+without action context keep their signatures but fail closed; callers needing a
+creation response must pass the explicit create decision. No database,
+authentication, authorization, proxy or stored-state migration is introduced.
+Rollback restores the older POST-action exposure and is not a security fix.
+Local focused verification passed 19 tests; immutable release and QA8080 native
+API Key lifecycle checks are still pending.
+
## Volume native classification
Published `0.183.332` exposes the existing `volume.isNative` boolean as read-only
diff --git a/README.md b/README.md
index 7342a7b88c..e628cf2b24 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,17 @@ preserved upstream boundary.
## Current release
+Candidate `v0.183.333` corrects a shared response-contract error: a POST action
+such as API Key deactivate is not resource creation. Schema fields marked
+read-on-create-only are now returned only for a genuine POST create, not for
+POST actions. The manager, response writer and attachment helper use the same
+request dispatch distinction. Other readable fields and v1/v2 role schemas are
+unchanged. Nineteen focused local tests passed (14 new regressions and five
+adjacent controls); formal artifact publication and QA8080 native acceptance
+are pending. See the [333 candidate note](docs/releases/orchestration-engine-0.183.333.md).
+
+## Historical 0.183.332 release
+
Published `v0.183.332` restores the server-owned Volume `isNative` classification
as a read-only field in both v1 frozen role schemas and v2 role overlays. It does
not change Volume CRUD permissions, infer missing fields in the browser, or
diff --git a/code/framework/api-pub-sub-jetty/pom.xml b/code/framework/api-pub-sub-jetty/pom.xml
index 542ba068e3..abc9a02471 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/api-pub-sub/pom.xml b/code/framework/api-pub-sub/pom.xml
index 3b0345b4ab..5cbfd58fb6 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/api/pom.xml b/code/framework/api/pom.xml
index a381c83636..96540730aa 100644
--- a/code/framework/api/pom.xml
+++ b/code/framework/api/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/api/src/main/java/io/cattle/platform/api/utils/ApiUtils.java b/code/framework/api/src/main/java/io/cattle/platform/api/utils/ApiUtils.java
index 22a8dae8ab..ae0b29fd4b 100644
--- a/code/framework/api/src/main/java/io/cattle/platform/api/utils/ApiUtils.java
+++ b/code/framework/api/src/main/java/io/cattle/platform/api/utils/ApiUtils.java
@@ -14,6 +14,7 @@
import io.github.ibuildthecloud.gdapi.model.impl.WrappedResource;
import io.github.ibuildthecloud.gdapi.request.ApiRequest;
import io.github.ibuildthecloud.gdapi.request.resource.ResourceManager;
+import io.github.ibuildthecloud.gdapi.util.RequestUtils;
import java.util.ArrayList;
import java.util.Arrays;
@@ -224,7 +225,8 @@ public Object apply(Object input) {
additionalFields.putAll(attachments);
}
String method = request == null ? null : request.getMethod();
- return new WrappedResource(idFormatter, schemaFactory, schema, obj, additionalFields, PRIORITY_FIELDS, method);
+ return new WrappedResource(idFormatter, schemaFactory, schema, obj, additionalFields, PRIORITY_FIELDS, method,
+ RequestUtils.isCreateRequest(request));
} finally {
DEPTH.set(depth);
}
diff --git a/code/framework/api/src/test/java/io/cattle/platform/api/schema/FileSchemaFactoryTest.java b/code/framework/api/src/test/java/io/cattle/platform/api/schema/FileSchemaFactoryTest.java
index 0cb2ec468b..962ce47579 100644
--- a/code/framework/api/src/test/java/io/cattle/platform/api/schema/FileSchemaFactoryTest.java
+++ b/code/framework/api/src/test/java/io/cattle/platform/api/schema/FileSchemaFactoryTest.java
@@ -284,6 +284,27 @@ private FileSchemaFactory factory(String resourceName, SchemaFactory schemaFacto
return factory;
}
+ @Test
+ public void preservesCreateOnlyApiKeyFlagInThePackagedFrozenV1UserSchema() throws Exception {
+ String resourceName = "schema/v1/user.ser";
+ Path root = Paths.get("").toAbsolutePath();
+ while (root != null && !Files.isRegularFile(root.resolve("resources/content/").resolve(resourceName))) {
+ root = root.getParent();
+ }
+ assertNotNull("Packaged frozen v1 schema is required", root);
+ Thread.currentThread().setContextClassLoader(new ResourceClassLoader(resourceName,
+ Files.readAllBytes(root.resolve("resources/content/").resolve(resourceName))));
+ FileSchemaFactory factory = factory(resourceName);
+ factory.start();
+
+ Schema keySchema = factory.getSchema("apiKey");
+ assertNotNull(keySchema);
+ FieldImpl field = (FieldImpl) keySchema.getResourceFields().get("secretValue");
+ assertNotNull(field);
+ assertTrue("Frozen v1 must retain the o overlay, not only the dynamic schema", field.isReadOnCreateOnly());
+ assertTrue(field.isIncludeInList());
+ }
+
private SchemaImpl schema(String id, String pluralName) {
SchemaImpl schema = new SchemaImpl();
schema.setId(id);
diff --git a/code/framework/api/src/test/java/io/cattle/platform/api/utils/ApiUtilsCreateOnlyTest.java b/code/framework/api/src/test/java/io/cattle/platform/api/utils/ApiUtilsCreateOnlyTest.java
new file mode 100644
index 0000000000..2f3c529532
--- /dev/null
+++ b/code/framework/api/src/test/java/io/cattle/platform/api/utils/ApiUtilsCreateOnlyTest.java
@@ -0,0 +1,142 @@
+package io.cattle.platform.api.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import io.github.ibuildthecloud.gdapi.context.ApiContext;
+import io.github.ibuildthecloud.gdapi.factory.impl.SchemaFactoryImpl;
+import io.github.ibuildthecloud.gdapi.model.Resource;
+import io.github.ibuildthecloud.gdapi.model.impl.FieldImpl;
+import io.github.ibuildthecloud.gdapi.model.impl.SchemaImpl;
+import io.github.ibuildthecloud.gdapi.request.ApiRequest;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ApiUtilsCreateOnlyTest {
+
+ private SchemaImpl schema;
+ private final TestBean bean = new TestBean();
+
+ @Before
+ public void createContextAndSchema() throws Exception {
+ ApiContext.newContext().setApiRequest(new ApiRequest(null, null));
+ schema = new SchemaImpl();
+ schema.setId("apiKey");
+ FieldImpl receipt = field("getCreationReceipt");
+ receipt.setReadOnCreateOnly(true);
+ schema.getResourceFields().put("creationReceipt", receipt);
+ schema.getResourceFields().put("secretValue", field("getSecretValue"));
+ schema.getResourceFields().put("name", field("getName"));
+ }
+
+ @After
+ public void removeContext() {
+ ApiContext.remove();
+ }
+
+ @Test
+ public void trueCreateAllowsBeanAndAdditionalFieldValuesInBothRoots() {
+ for (String version : Arrays.asList("v1", "v2-beta")) {
+ assertFields(render(request(version, "POST", null), null), "unit-bean-receipt");
+ Map extra = extras();
+ assertFields(render(request(version, "POST", null), extra), "unit-additional-receipt");
+ assertEquals("The caller's map must not be consumed", extras(), extra);
+ }
+ }
+
+ @Test
+ public void postActionsRedactBothValueSourcesWithoutRedactingUnflaggedNames() {
+ for (String version : Arrays.asList("v1", "v2-beta")) {
+ for (String action : Arrays.asList("deactivate", "activate", "remove", "update", "")) {
+ assertFields(render(request(version, "POST", action), null), null);
+ Map extra = extras();
+ assertFields(render(request(version, "POST", action), extra), null);
+ assertEquals(extras(), extra);
+ }
+ }
+ assertEquals("The underlying bean is not scrubbed or mutated", "unit-bean-receipt", bean.getCreationReceipt());
+ }
+
+ @Test
+ public void nullRequestFailsClosedForBothValueSources() {
+ assertFields(render(null, null), null);
+ Map extra = extras();
+ assertFields(render(null, extra), null);
+ assertEquals(extras(), extra);
+ }
+
+ @Test
+ public void readUpdateAndDeleteCannotUseTheCreateException() {
+ for (String version : Arrays.asList("v1", "v2-beta")) {
+ for (String method : Arrays.asList("GET", "PUT", "DELETE")) {
+ assertFields(render(request(version, method, null), null), null);
+ assertFields(render(request(version, method, null), extras()), null);
+ }
+ }
+ }
+
+ private FieldImpl field(String getter) throws Exception {
+ FieldImpl field = new FieldImpl();
+ field.setType("string");
+ field.setReadMethod(TestBean.class.getMethod(getter));
+ return field;
+ }
+
+ private ApiRequest request(String version, String method, String action) {
+ ApiRequest request = new ApiRequest(null, null);
+ request.setVersion(version);
+ request.setMethod(method);
+ request.setAction(action);
+ return request;
+ }
+
+ private Resource render(ApiRequest request, Map extra) {
+ return ApiUtils.createResourceWithAttachments(null, request,
+ ApiContext.getContext().getIdFormatter(), new SchemaFactoryImpl(), schema, bean, extra);
+ }
+
+ private Map extras() {
+ Map fields = new LinkedHashMap();
+ fields.put("creationReceipt", "unit-additional-receipt");
+ return fields;
+ }
+
+ private void assertFields(Resource resource, String receipt) {
+ if (receipt == null) {
+ assertNull(resource.getFields().get("creationReceipt"));
+ } else {
+ assertEquals(receipt, resource.getFields().get("creationReceipt"));
+ }
+ assertEquals("unit-ordinary-field", resource.getFields().get("secretValue"));
+ assertEquals("ordinary-name", resource.getFields().get("name"));
+ }
+
+ public static class TestBean {
+ public Long getId() {
+ return 73L;
+ }
+
+ public Map getData() {
+ return Collections.emptyMap();
+ }
+
+ public String getCreationReceipt() {
+ return "unit-bean-receipt";
+ }
+
+ public String getSecretValue() {
+ return "unit-ordinary-field";
+ }
+
+ public String getName() {
+ return "ordinary-name";
+ }
+ }
+}
diff --git a/code/framework/archaius/pom.xml b/code/framework/archaius/pom.xml
index d8b4a3cdc2..592abcf4d1 100644
--- a/code/framework/archaius/pom.xml
+++ b/code/framework/archaius/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-meta-parent
- 0.183.332
+ 0.183.333
../../meta-parent/pom.xml
diff --git a/code/framework/async/pom.xml b/code/framework/async/pom.xml
index ef369bfb54..c765c45467 100644
--- a/code/framework/async/pom.xml
+++ b/code/framework/async/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/auditing/pom.xml b/code/framework/auditing/pom.xml
index 70434a0304..0510f82794 100644
--- a/code/framework/auditing/pom.xml
+++ b/code/framework/auditing/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/db-loader/pom.xml b/code/framework/db-loader/pom.xml
index 1b5d4b7913..7104c15210 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/deferred/pom.xml b/code/framework/deferred/pom.xml
index f81f10cd98..77a8d3cd94 100644
--- a/code/framework/deferred/pom.xml
+++ b/code/framework/deferred/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/encryption/pom.xml b/code/framework/encryption/pom.xml
index 64f5744ae6..2e2fcee6f8 100644
--- a/code/framework/encryption/pom.xml
+++ b/code/framework/encryption/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/engine/pom.xml b/code/framework/engine/pom.xml
index 2b426f6a34..91ba9b25e6 100644
--- a/code/framework/engine/pom.xml
+++ b/code/framework/engine/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/eventing/pom.xml b/code/framework/eventing/pom.xml
index 7b2bb95d0e..64b1a7b7e6 100644
--- a/code/framework/eventing/pom.xml
+++ b/code/framework/eventing/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/events/pom.xml b/code/framework/events/pom.xml
index 891131a182..579214411c 100644
--- a/code/framework/events/pom.xml
+++ b/code/framework/events/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/extension-spring/pom.xml b/code/framework/extension-spring/pom.xml
index 2ac3b20f77..3068cb5cb9 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/extension/pom.xml b/code/framework/extension/pom.xml
index d797540e88..ec376eb44f 100644
--- a/code/framework/extension/pom.xml
+++ b/code/framework/extension/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/java-server/pom.xml b/code/framework/java-server/pom.xml
index 3c8c0de1e4..572e6b6652 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/model/impl/WrappedResource.java b/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/model/impl/WrappedResource.java
index eb2ca3a8ba..2a179ddcdb 100644
--- a/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/model/impl/WrappedResource.java
+++ b/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/model/impl/WrappedResource.java
@@ -30,13 +30,21 @@ public class WrappedResource extends ResourceImpl implements Resource {
Map additionalFields;
Map resourceFields;
boolean createTsFields = true;
- String method;
+ boolean createResponse;
Set priorityFieldNames = null;
IdFormatter idFormatter;
+ /** Legacy callers without request action context fail closed for create-only fields. */
public WrappedResource(IdFormatter idFormatter, SchemaFactory schemaFactory,
Schema schema, Object obj, Map additionalFields,
Set priorityFieldNames, String method) {
+ this(idFormatter, schemaFactory, schema, obj, additionalFields, priorityFieldNames, method, false);
+ }
+
+ /** A create response requires both POST and the caller's explicit create/action decision. */
+ public WrappedResource(IdFormatter idFormatter, SchemaFactory schemaFactory,
+ Schema schema, Object obj, Map additionalFields,
+ Set priorityFieldNames, String method, boolean createResponse) {
super();
this.schemaFactory = schemaFactory;
this.schema = schema;
@@ -45,7 +53,7 @@ public WrappedResource(IdFormatter idFormatter, SchemaFactory schemaFactory,
this.idFormatter = idFormatter;
this.additionalFields = additionalFields;
this.priorityFieldNames = priorityFieldNames;
- this.method = method;
+ this.createResponse = Schema.Method.POST.isMethod(method) && createResponse;
init();
}
@@ -53,6 +61,10 @@ public WrappedResource(IdFormatter idFormatter, SchemaFactory schemaFactory, Sch
this(idFormatter, schemaFactory, schema, obj, new HashMap(), null, method);
}
+ public WrappedResource(IdFormatter idFormatter, SchemaFactory schemaFactory, Schema schema, Object obj, String method, boolean createResponse) {
+ this(idFormatter, schemaFactory, schema, obj, new HashMap(), null, method, createResponse);
+ }
+
protected void addField(String key, Object value) {
if (priorityFieldNames != null && priorityFieldNames.contains(key)) {
priorityFields.put(key, value);
@@ -75,7 +87,7 @@ protected void init() {
if (value == null) {
value = field.getValue(obj);
}
- if (!Schema.Method.POST.isMethod(method) && field.isReadOnCreateOnly()){
+ if (!createResponse && field.isReadOnCreateOnly()){
value = null;
}
if (StringUtils.isNotBlank(field.getTransform()) && StringUtils.isNotBlank((String) value)){
diff --git a/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/request/resource/impl/AbstractBaseResourceManager.java b/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/request/resource/impl/AbstractBaseResourceManager.java
index 457f9672db..f973338d58 100644
--- a/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/request/resource/impl/AbstractBaseResourceManager.java
+++ b/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/request/resource/impl/AbstractBaseResourceManager.java
@@ -358,7 +358,7 @@ protected void addActions(Object obj, SchemaFactory schemaFactory, Schema schema
}
protected Resource constructResource(IdFormatter idFormatter, SchemaFactory schemaFactory, Schema schema, Object obj, ApiRequest apiRequest) {
- return new WrappedResource(idFormatter, schemaFactory, schema, obj, apiRequest.getMethod());
+ return new WrappedResource(idFormatter, schemaFactory, schema, obj, apiRequest.getMethod(), RequestUtils.isCreateRequest(apiRequest));
}
protected void addLinks(Object obj, SchemaFactory schemaFactory, Schema schema, Resource resource) {
diff --git a/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/response/JsonResponseWriter.java b/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/response/JsonResponseWriter.java
index 24d68813f3..4a792f295b 100644
--- a/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/response/JsonResponseWriter.java
+++ b/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/response/JsonResponseWriter.java
@@ -11,6 +11,7 @@
import io.github.ibuildthecloud.gdapi.model.impl.WrappedResource;
import io.github.ibuildthecloud.gdapi.request.ApiRequest;
import io.github.ibuildthecloud.gdapi.request.handler.AbstractApiRequestHandler;
+import io.github.ibuildthecloud.gdapi.util.RequestUtils;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
@@ -105,7 +106,9 @@ protected Resource createResource(SchemaFactory schemaFactory, Object obj) {
Schema schema = schemaFactory.getSchema(obj.getClass());
ApiContext apiContext = ApiContext.getContext();
- return schema == null ? null : new WrappedResource(apiContext.getIdFormatter(), schemaFactory, schema, obj, apiContext.getApiRequest().getMethod());
+ ApiRequest request = apiContext.getApiRequest();
+ return schema == null ? null : new WrappedResource(apiContext.getIdFormatter(), schemaFactory, schema, obj,
+ request.getMethod(), RequestUtils.isCreateRequest(request));
}
protected void writeJson(JsonMapper jsonMapper, OutputStream os, Object responseObject, ApiRequest request) throws IOException {
diff --git a/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/util/RequestUtils.java b/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/util/RequestUtils.java
index 687e1a2f2b..1b310b8a70 100644
--- a/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/util/RequestUtils.java
+++ b/code/framework/java-server/src/main/java/io/github/ibuildthecloud/gdapi/util/RequestUtils.java
@@ -39,6 +39,11 @@ public static boolean isWriteMethod(String method) {
return POST.isMethod(method) || PUT.isMethod(method) || DELETE.isMethod(method);
}
+ /** Uses the same create/action distinction as ResourceManagerRequestHandler. */
+ public static boolean isCreateRequest(ApiRequest request) {
+ return request != null && POST.isMethod(request.getMethod()) && request.getAction() == null;
+ }
+
public static boolean mayHaveBody(String method) {
return POST.isMethod(method) || PUT.isMethod(method);
}
diff --git a/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/CreateOnlyCallerTest.java b/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/CreateOnlyCallerTest.java
new file mode 100644
index 0000000000..8c1b1e5b1e
--- /dev/null
+++ b/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/CreateOnlyCallerTest.java
@@ -0,0 +1,131 @@
+package io.github.ibuildthecloud.gdapi.model.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import io.github.ibuildthecloud.gdapi.context.ApiContext;
+import io.github.ibuildthecloud.gdapi.factory.SchemaFactory;
+import io.github.ibuildthecloud.gdapi.factory.impl.SchemaFactoryImpl;
+import io.github.ibuildthecloud.gdapi.model.Resource;
+import io.github.ibuildthecloud.gdapi.model.Schema;
+import io.github.ibuildthecloud.gdapi.request.ApiRequest;
+import io.github.ibuildthecloud.gdapi.request.resource.impl.AbstractNoOpResourceManager;
+import io.github.ibuildthecloud.gdapi.response.JsonResponseWriter;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CreateOnlyCallerTest {
+
+ private SchemaFactoryImpl factory;
+ private Schema schema;
+ private final TestBean bean = new TestBean();
+
+ @Before
+ public void createContextAndBeanSchema() {
+ ApiContext.newContext();
+ factory = new SchemaFactoryImpl();
+ factory.setIncludeDefaultTypes(false);
+ factory.setTypes(Collections.>singletonList(TestBean.class));
+ factory.init();
+ schema = factory.getSchema(TestBean.class);
+ FieldImpl receipt = (FieldImpl) schema.getResourceFields().get("creationReceipt");
+ assertNotNull("Use the actual bean getter, not additionalFields", receipt.getReadMethod());
+ receipt.setReadOnCreateOnly(true);
+ }
+
+ @After
+ public void removeContext() {
+ ApiContext.remove();
+ }
+
+ @Test
+ public void managerConstructResourceUsesTheRequestActionNotOnlyPostMethod() {
+ ExposedManager manager = new ExposedManager();
+ for (String version : Arrays.asList("v1", "v2-beta")) {
+ assertFields(manager.render(factory, schema, bean, request(version, "POST", null)), true);
+ for (String action : Arrays.asList("deactivate", "activate", "remove", "update", "")) {
+ assertFields(manager.render(factory, schema, bean, request(version, "POST", action)), false);
+ }
+ for (String method : Arrays.asList("GET", "PUT", "DELETE")) {
+ assertFields(manager.render(factory, schema, bean, request(version, method, null)), false);
+ }
+ }
+ assertEquals("unit-bean-receipt", bean.getCreationReceipt());
+ }
+
+ @Test
+ public void responseWriterCreateResourceUsesTheActualContextRequest() {
+ ExposedWriter writer = new ExposedWriter();
+ for (String version : Arrays.asList("v1", "v2-beta")) {
+ ApiContext.getContext().setApiRequest(request(version, "POST", null));
+ assertFields(writer.render(factory, bean), true);
+ for (String action : Arrays.asList("deactivate", "activate", "remove", "update", "")) {
+ ApiContext.getContext().setApiRequest(request(version, "POST", action));
+ assertFields(writer.render(factory, bean), false);
+ }
+ for (String method : Arrays.asList("GET", "PUT", "DELETE")) {
+ ApiContext.getContext().setApiRequest(request(version, method, null));
+ assertFields(writer.render(factory, bean), false);
+ }
+ }
+ assertEquals("unit-bean-receipt", bean.getCreationReceipt());
+ }
+
+ private ApiRequest request(String version, String method, String action) {
+ ApiRequest request = new ApiRequest(null, null);
+ request.setVersion(version);
+ request.setMethod(method);
+ request.setAction(action);
+ return request;
+ }
+
+ private void assertFields(Resource resource, boolean creation) {
+ Map fields = resource.getFields();
+ if (creation) {
+ assertEquals("unit-bean-receipt", fields.get("creationReceipt"));
+ } else {
+ assertNull(fields.get("creationReceipt"));
+ }
+ // Redaction follows the schema's o flag, not a hard-coded secret field name.
+ assertEquals("unit-ordinary-field", fields.get("secretValue"));
+ assertEquals("ordinary-name", fields.get("name"));
+ }
+
+ public static class TestBean {
+ public String getCreationReceipt() {
+ return "unit-bean-receipt";
+ }
+
+ public String getSecretValue() {
+ return "unit-ordinary-field";
+ }
+
+ public String getName() {
+ return "ordinary-name";
+ }
+ }
+
+ private static class ExposedManager extends AbstractNoOpResourceManager {
+ @Override
+ public Class>[] getTypeClasses() {
+ return new Class>[0];
+ }
+
+ Resource render(SchemaFactory factory, Schema schema, Object obj, ApiRequest request) {
+ return super.constructResource(ApiContext.getContext().getIdFormatter(), factory, schema, obj, request);
+ }
+ }
+
+ private static class ExposedWriter extends JsonResponseWriter {
+ Resource render(SchemaFactory factory, Object obj) {
+ return super.createResource(factory, obj);
+ }
+ }
+}
diff --git a/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/CreateOnlyWrappedResourceTest.java b/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/CreateOnlyWrappedResourceTest.java
new file mode 100644
index 0000000000..cdb3503af3
--- /dev/null
+++ b/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/CreateOnlyWrappedResourceTest.java
@@ -0,0 +1,100 @@
+package io.github.ibuildthecloud.gdapi.model.impl;
+
+import static org.junit.Assert.*;
+
+import io.github.ibuildthecloud.gdapi.factory.SchemaFactory;
+import io.github.ibuildthecloud.gdapi.factory.impl.SchemaFactoryImpl;
+import io.github.ibuildthecloud.gdapi.id.IdFormatter;
+import io.github.ibuildthecloud.gdapi.request.ApiRequest;
+import io.github.ibuildthecloud.gdapi.util.RequestUtils;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+
+public class CreateOnlyWrappedResourceTest {
+ private final IdFormatter ids = new IdFormatter() {
+ public Object formatId(String type, Object id) { return id; }
+ public String parseId(String id) { return id; }
+ public IdFormatter withSchemaFactory(SchemaFactory factory) { return this; }
+ };
+
+ private SchemaImpl schema(boolean createOnly) {
+ SchemaImpl schema = new SchemaImpl();
+ schema.setId("apiKey");
+ FieldImpl field = new FieldImpl();
+ field.setType("string");
+ field.setReadOnCreateOnly(createOnly);
+ schema.getResourceFields().put("secretValue", field);
+ FieldImpl name = new FieldImpl();
+ name.setType("string");
+ schema.getResourceFields().put("name", name);
+ return schema;
+ }
+
+ private Map values() {
+ Map values = new HashMap();
+ values.put("secretValue", "unit-test-sentinel");
+ values.put("name", "ordinary-name");
+ return values;
+ }
+
+ private Map render(String method, String action, String version, boolean createOnly) {
+ ApiRequest request = new ApiRequest(null, null);
+ request.setMethod(method);
+ request.setAction(action);
+ request.setVersion(version);
+ return new WrappedResource(ids, new SchemaFactoryImpl(), schema(createOnly), null, values(), null,
+ request.getMethod(), RequestUtils.isCreateRequest(request)).getFields();
+ }
+
+ @Test
+ public void trueCreationRetainsTheFirstSecretInBothApiVersions() {
+ for (String version : new String[] {"v1", "v2-beta"}) {
+ assertEquals("unit-test-sentinel", render("POST", null, version, true).get("secretValue"));
+ }
+ }
+
+ @Test
+ public void postActionsCannotRevealCreateOnlyValues() {
+ for (String version : new String[] {"v1", "v2-beta"}) {
+ for (String action : new String[] {"deactivate", "activate", "remove", "update", "", "unknown"}) {
+ Map result = render("POST", action, version, true);
+ assertNull(result.get("secretValue"));
+ assertEquals("ordinary-name", result.get("name"));
+ }
+ }
+ }
+
+ @Test
+ public void readUpdateDeleteAndUnknownMethodsStillRedact() {
+ for (String method : new String[] {"GET", "PUT", "DELETE", "HEAD", "OPTIONS", "UNKNOWN", null}) {
+ assertNull(render(method, null, "v2-beta", true).get("secretValue"));
+ // A caller cannot make a non-POST request expose creation fields.
+ assertNull(new WrappedResource(ids, new SchemaFactoryImpl(), schema(true), null, values(), null,
+ method, true).getFields().get("secretValue"));
+ }
+ }
+
+ @Test
+ public void rolesWithoutCreateOnlyRestrictionKeepTheirExistingReadContract() {
+ for (String method : new String[] {"GET", "PUT", "DELETE", "POST"}) {
+ assertEquals("unit-test-sentinel", render(method, "deactivate", "v1", false).get("secretValue"));
+ }
+ }
+
+ @Test
+ public void methodOnlyLegacyConstructorsFailClosedInsteadOfGuessingCreation() {
+ assertNull(new WrappedResource(ids, new SchemaFactoryImpl(), schema(true), null, values(), null,
+ "POST").getFields().get("secretValue"));
+ assertNull(new WrappedResource(ids, new SchemaFactoryImpl(), schema(true), null, "POST")
+ .getFields().get("secretValue"));
+ }
+
+ @Test
+ public void priorityFieldsCannotBypassTheCreateOnlyBoundary() {
+ Map result = new WrappedResource(ids, new SchemaFactoryImpl(), schema(true), null,
+ values(), java.util.Collections.singleton("secretValue"), "POST", false).getFields();
+ assertNull(result.get("secretValue"));
+ assertEquals("ordinary-name", result.get("name"));
+ }
+}
diff --git a/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/util/RequestUtilsTest.java b/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/util/RequestUtilsTest.java
index 286720d368..5dd02abb61 100644
--- a/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/util/RequestUtilsTest.java
+++ b/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/util/RequestUtilsTest.java
@@ -8,9 +8,28 @@
import java.util.Map;
import org.junit.Test;
+import io.github.ibuildthecloud.gdapi.request.ApiRequest;
public class RequestUtilsTest {
+ @Test
+ public void creationRequiresPostAndAbsentActionNotAStatusCode() {
+ assertFalse(RequestUtils.isCreateRequest(null));
+ ApiRequest request = new ApiRequest(null, null);
+ assertFalse(RequestUtils.isCreateRequest(request));
+ request.setMethod("POST");
+ request.setResponseCode(202);
+ assertTrue(RequestUtils.isCreateRequest(request));
+ for (String action : new String[] {"deactivate", "activate", "remove", ""}) {
+ request.setAction(action);
+ request.setResponseCode(201);
+ assertFalse(RequestUtils.isCreateRequest(request));
+ }
+ request.setAction(null);
+ request.setMethod("PUT");
+ assertFalse(RequestUtils.isCreateRequest(request));
+ }
+
@Test
public void toMapPreservesStringKeysAndIterationOrder() {
Map input = new LinkedHashMap();
diff --git a/code/framework/jmx/pom.xml b/code/framework/jmx/pom.xml
index 9e95ab3fa9..c8f7fc3763 100644
--- a/code/framework/jmx/pom.xml
+++ b/code/framework/jmx/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/jooq/pom.xml b/code/framework/jooq/pom.xml
index e9c7a92c6a..19567b098d 100644
--- a/code/framework/jooq/pom.xml
+++ b/code/framework/jooq/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/json/pom.xml b/code/framework/json/pom.xml
index 2a429b8355..bd9f083336 100644
--- a/code/framework/json/pom.xml
+++ b/code/framework/json/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/launcher/pom.xml b/code/framework/launcher/pom.xml
index 4f2be9512f..f4500e4115 100644
--- a/code/framework/launcher/pom.xml
+++ b/code/framework/launcher/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/lock/pom.xml b/code/framework/lock/pom.xml
index b8e257b0c1..22743a62bd 100644
--- a/code/framework/lock/pom.xml
+++ b/code/framework/lock/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/logback/pom.xml b/code/framework/logback/pom.xml
index 9dec7da6de..1cb9ab0ff4 100644
--- a/code/framework/logback/pom.xml
+++ b/code/framework/logback/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-meta-parent
- 0.183.332
+ 0.183.333
../../meta-parent/pom.xml
diff --git a/code/framework/managed-context/pom.xml b/code/framework/managed-context/pom.xml
index f658a4acf3..588607ba7d 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/metrics/pom.xml b/code/framework/metrics/pom.xml
index 1d9a351daa..e7dab54bb0 100644
--- a/code/framework/metrics/pom.xml
+++ b/code/framework/metrics/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/module/pom.xml b/code/framework/module/pom.xml
index c2085d6e16..e0d418773e 100644
--- a/code/framework/module/pom.xml
+++ b/code/framework/module/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/object/pom.xml b/code/framework/object/pom.xml
index 562cca778a..42a103c738 100644
--- a/code/framework/object/pom.xml
+++ b/code/framework/object/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/pool/pom.xml b/code/framework/pool/pom.xml
index e911c39c6d..9eff127eaa 100644
--- a/code/framework/pool/pom.xml
+++ b/code/framework/pool/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/resource-monitor/pom.xml b/code/framework/resource-monitor/pom.xml
index 4d6e90e47f..1753fde63a 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/schema/pom.xml b/code/framework/schema/pom.xml
index af23127f38..db385a8d75 100644
--- a/code/framework/schema/pom.xml
+++ b/code/framework/schema/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/server/pom.xml b/code/framework/server/pom.xml
index d671c4d71a..97fd0bbe70 100644
--- a/code/framework/server/pom.xml
+++ b/code/framework/server/pom.xml
@@ -4,7 +4,7 @@
cattle-meta-parent
io.cattle
- 0.183.332
+ 0.183.333
../../meta-parent/pom.xml
diff --git a/code/framework/spring/pom.xml b/code/framework/spring/pom.xml
index 51f38984c9..03b952d5d4 100644
--- a/code/framework/spring/pom.xml
+++ b/code/framework/spring/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/system-task/pom.xml b/code/framework/system-task/pom.xml
index a1c58d9647..81fead9143 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/token/pom.xml b/code/framework/token/pom.xml
index a2d0821c9b..5f3d393d0a 100644
--- a/code/framework/token/pom.xml
+++ b/code/framework/token/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/framework/utils/pom.xml b/code/framework/utils/pom.xml
index 981229acdb..89e337cea4 100644
--- a/code/framework/utils/pom.xml
+++ b/code/framework/utils/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/agent-instance/pom.xml b/code/iaas/agent-instance/pom.xml
index fbfb2b60f9..ae439e68fe 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/agent-server/pom.xml b/code/iaas/agent-server/pom.xml
index 520bc189c4..f6d4d770da 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/agent/pom.xml b/code/iaas/agent/pom.xml
index fa3d5a9245..c9fd24457e 100644
--- a/code/iaas/agent/pom.xml
+++ b/code/iaas/agent/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/allocator/pom.xml b/code/iaas/allocator/pom.xml
index 86143996c9..28b75edf4f 100644
--- a/code/iaas/allocator/pom.xml
+++ b/code/iaas/allocator/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/api-logic/pom.xml b/code/iaas/api-logic/pom.xml
index 194690cd1f..b5af65f370 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/archaius-management/pom.xml b/code/iaas/archaius-management/pom.xml
index 9da2859121..83bee59a9c 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/auth-logic/pom.xml b/code/iaas/auth-logic/pom.xml
index 660d1f8e43..e8ca7012fb 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/bootstrap/pom.xml b/code/iaas/bootstrap/pom.xml
index fadcd2e069..d443d9cf92 100644
--- a/code/iaas/bootstrap/pom.xml
+++ b/code/iaas/bootstrap/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/config-item/api/pom.xml b/code/iaas/config-item/api/pom.xml
index eb53a83dce..553eb1db15 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/iaas/config-item/common/pom.xml b/code/iaas/config-item/common/pom.xml
index 385fc91300..538410e287 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/iaas/config-item/server/pom.xml b/code/iaas/config-item/server/pom.xml
index abd82f0f1e..6d5f1b2599 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/iaas/engine-jooq/pom.xml b/code/iaas/engine-jooq/pom.xml
index 69ebc8b2ba..b720a1d725 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/events/pom.xml b/code/iaas/events/pom.xml
index e6a34b1925..95f8e12935 100644
--- a/code/iaas/events/pom.xml
+++ b/code/iaas/events/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/external-handler/pom.xml b/code/iaas/external-handler/pom.xml
index 8661a46b8f..f3825bbc8f 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/ha/pom.xml b/code/iaas/ha/pom.xml
index 9161fcbf8b..f2397c5ec4 100644
--- a/code/iaas/ha/pom.xml
+++ b/code/iaas/ha/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/healthcheck/pom.xml b/code/iaas/healthcheck/pom.xml
index bca1be4570..621f336739 100644
--- a/code/iaas/healthcheck/pom.xml
+++ b/code/iaas/healthcheck/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/labels/pom.xml b/code/iaas/labels/pom.xml
index 17f885276f..ed592bc678 100644
--- a/code/iaas/labels/pom.xml
+++ b/code/iaas/labels/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/logic-common/pom.xml b/code/iaas/logic-common/pom.xml
index 1183ffb0f1..a700966f65 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/logic/pom.xml b/code/iaas/logic/pom.xml
index 5f5f6e52e4..e03a3b059e 100644
--- a/code/iaas/logic/pom.xml
+++ b/code/iaas/logic/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/metadata/pom.xml b/code/iaas/metadata/pom.xml
index 7e7c916619..68364ac054 100644
--- a/code/iaas/metadata/pom.xml
+++ b/code/iaas/metadata/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/model/pom.xml b/code/iaas/model/pom.xml
index 3f2ff636f7..b61bc8ad75 100644
--- a/code/iaas/model/pom.xml
+++ b/code/iaas/model/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/resource-pool/pom.xml b/code/iaas/resource-pool/pom.xml
index f350eceffe..fc4fd490d8 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/service-discovery/api/pom.xml b/code/iaas/service-discovery/api/pom.xml
index e810e41f68..71ca08fcf6 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/iaas/service-discovery/server/pom.xml b/code/iaas/service-discovery/server/pom.xml
index 8b21b223e8..4eb9981165 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/iaas/ssh-common/pom.xml b/code/iaas/ssh-common/pom.xml
index 3755e1f488..8c0d565ca6 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/storage-service/pom.xml b/code/iaas/storage-service/pom.xml
index a18dd3bd70..bd9d0b43f0 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/iaas/task-jooq/pom.xml b/code/iaas/task-jooq/pom.xml
index c41976cef6..f4492ad879 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/implementation/activity-log/pom.xml b/code/implementation/activity-log/pom.xml
index 2806130e00..74bbcdfde1 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/implementation/agent-instance-impl/pom.xml b/code/implementation/agent-instance-impl/pom.xml
index c708dc8149..9655cf590f 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.332
+ 0.183.333
../../parent/pom.xml
cattle-agent-instance-impl
diff --git a/code/implementation/docker/api/pom.xml b/code/implementation/docker/api/pom.xml
index 939dcf286e..fb066d35c4 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/implementation/docker/common/pom.xml b/code/implementation/docker/common/pom.xml
index e10c10dd15..4da2857416 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/implementation/docker/compute/pom.xml b/code/implementation/docker/compute/pom.xml
index cbf39e750e..ec27fceade 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/implementation/docker/machine/pom.xml b/code/implementation/docker/machine/pom.xml
index 8cecef902c..0a0cfb479e 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/implementation/docker/storage/pom.xml b/code/implementation/docker/storage/pom.xml
index bf15099056..d8466dee1a 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.332
+ 0.183.333
../../../parent/pom.xml
@@ -21,12 +21,12 @@
io.cattle
cattle-docker-common
- 0.183.332
+ 0.183.333
io.cattle
cattle-iaas-allocator
- 0.183.332
+ 0.183.333
diff --git a/code/implementation/extension-api/pom.xml b/code/implementation/extension-api/pom.xml
index f324bddbf5..c029794db8 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.332
+ 0.183.333
../../parent/pom.xml
cattle-extension-api
diff --git a/code/implementation/hazelcast/common/pom.xml b/code/implementation/hazelcast/common/pom.xml
index e2e7433263..2917586cf5 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/implementation/hazelcast/eventing/pom.xml b/code/implementation/hazelcast/eventing/pom.xml
index fae72b111f..e90dcd6b1c 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/implementation/hazelcast/lock/pom.xml b/code/implementation/hazelcast/lock/pom.xml
index c78afd19c5..5f4afac26b 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/implementation/host-api/pom.xml b/code/implementation/host-api/pom.xml
index c6b446ada6..21f68027aa 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/implementation/host-stats/pom.xml b/code/implementation/host-stats/pom.xml
index 23c95a6e6e..bd7a64185c 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/implementation/register/pom.xml b/code/implementation/register/pom.xml
index 117556f4f2..176d71ffca 100644
--- a/code/implementation/register/pom.xml
+++ b/code/implementation/register/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/implementation/sample-setup/pom.xml b/code/implementation/sample-setup/pom.xml
index 16b7cbad39..e2a6100672 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/implementation/settings-api/pom.xml b/code/implementation/settings-api/pom.xml
index ba8f5e2b5f..a9624727b2 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/implementation/simulator/agent-connection/pom.xml b/code/implementation/simulator/agent-connection/pom.xml
index 5cdf223aee..9f0932d345 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/implementation/simulator/storage/pom.xml b/code/implementation/simulator/storage/pom.xml
index 217938ad55..1d1a5c548b 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.332
+ 0.183.333
../../../parent/pom.xml
diff --git a/code/implementation/system-stack/pom.xml b/code/implementation/system-stack/pom.xml
index 9803ec614f..6527670533 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.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/implementation/vm/pom.xml b/code/implementation/vm/pom.xml
index ded78f922e..a18782dc2d 100644
--- a/code/implementation/vm/pom.xml
+++ b/code/implementation/vm/pom.xml
@@ -3,7 +3,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
cattle-vm
diff --git a/code/meta-parent/pom.xml b/code/meta-parent/pom.xml
index fcb8e2256a..c48362fb1b 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.332
+ 0.183.333
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 9d9ea0f164..f28ef93712 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.332
+ 0.183.333
../../parent/pom.xml
jar
diff --git a/code/packaging/app/pom.xml b/code/packaging/app/pom.xml
index 0ce5ed47e0..6bc471c088 100644
--- a/code/packaging/app/pom.xml
+++ b/code/packaging/app/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
war
diff --git a/code/packaging/bundle/pom.xml b/code/packaging/bundle/pom.xml
index 9cb6c78484..79d7a195d6 100644
--- a/code/packaging/bundle/pom.xml
+++ b/code/packaging/bundle/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/packaging/dev/pom.xml b/code/packaging/dev/pom.xml
index e478f5e0c9..5328f1d1c3 100644
--- a/code/packaging/dev/pom.xml
+++ b/code/packaging/dev/pom.xml
@@ -4,7 +4,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/packaging/meta/pom.xml b/code/packaging/meta/pom.xml
index a3479a6f67..0799e53805 100644
--- a/code/packaging/meta/pom.xml
+++ b/code/packaging/meta/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../../parent/pom.xml
diff --git a/code/parent/pom.xml b/code/parent/pom.xml
index c15fcf2646..e7892aa292 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.332
+ 0.183.333
pom
diff --git a/docs/releases/orchestration-engine-0.183.333.md b/docs/releases/orchestration-engine-0.183.333.md
new file mode 100644
index 0000000000..a938b92d6f
--- /dev/null
+++ b/docs/releases/orchestration-engine-0.183.333.md
@@ -0,0 +1,44 @@
+# Orchestration Engine 0.183.333 — candidate
+
+## Root cause and scope
+
+`WrappedResource` treated every POST response as a creation response. An API Key
+deactivate action returns the reloaded credential, so its stored `secretValue`
+could appear despite the schema's read-on-create-only contract. This observation
+does not establish that the stored value was a plaintext secret; it still breaks
+the response boundary. GET and PUT redaction did not establish POST-action safety.
+
+The fix shares the actual resource dispatch distinction (`POST` and no action)
+across the manager, JSON writer and attachment helper. Fields marked `o` are
+redacted for actions as well as reads, updates and deletes. The existing null
+representation is retained. A true create still delivers its first secret.
+Other readable fields are not name-matched or hidden; API schemas, role overlays,
+account boundaries and persistent data are unchanged. Legacy wrapper signatures
+remain available and fail closed without explicit creation context.
+
+## Focused verification
+
+Nineteen local tests passed, zero failures/errors/skips: 14 new regressions and
+five adjacent controls. Coverage includes true creation, POST actions (including
+empty/unknown actions), other methods, both API roots, actual manager/writer and
+attachment callers, bean and additional-field values, priority fields, legacy
+constructors, ordinary readable fields, the actual frozen v1 user API Key `o`
+flag, and the existing Volume formatter contract. An independent read-only
+source review found no confirmed surviving bypass or introduced regression in
+the five changed production files. The formal release gate requires the new
+named regressions in its executed unit-case evidence.
+
+## Pending acceptance
+
+This is not yet a published component or Server image. Exact CI artifact
+readback, isolated startup, immutable publication, Server packaging and QA8080
+native API Key lifecycle acceptance remain required. Old failed QA receipts stay
+HOLD; they are not rewritten as PASS. The full resource/role matrix is incomplete.
+
+## Upgrade and rollback
+
+No migration is required. Preserve Compose environment, named volumes, restart
+policy, AppArmor, origin and authentication settings. Consume only a new immutable
+Server image after the component gates pass; do not overwrite prior tags. A
+rollback restores the old POST-action response behavior and must not be described
+as preserving this fix. No production deployment is authorized by this candidate.
diff --git a/pom.xml b/pom.xml
index 238134b00a..d1f0ab913d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
io.cattle
cattle-parent
- 0.183.332
+ 0.183.333
code/parent/pom.xml
cattle
diff --git a/resources/pom.xml b/resources/pom.xml
index 6568faff64..eb821685ae 100644
--- a/resources/pom.xml
+++ b/resources/pom.xml
@@ -4,7 +4,7 @@
cattle-parent
io.cattle
- 0.183.332
+ 0.183.333
../code/parent/pom.xml
diff --git a/scripts/build b/scripts/build
index fd96e0e1aa..97b0cd353b 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.332}
+ENGINE_VERSION=${ENGINE_VERSION:-0.183.333}
case "$SOURCE_REVISION" in
''|*[!0-9a-f]*)
diff --git a/scripts/check-pasturestack-source b/scripts/check-pasturestack-source
index fa4ba9ceec..7d5f953ce4 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.332'
+require_line code/meta-parent/pom.xml ' 0.183.333'
require_line code/meta-parent/pom.xml ' 2.3.35'
require_line "$iaas_api_defaults" 'auth.service.external.id.types=github_user,github_org,github_team,shibboleth_user,shibboleth_group,ldap_user,ldap_group,oidc_user,oidc_group'
require_line code/meta-parent/pom.xml ' https://github.com/PastureStack/orchestration-engine'
@@ -418,4 +418,4 @@ require_line README.md 'modernize the Rancher 1.6 ecosystem. It is not affiliate
require_line README.md 'by Rancher Labs or SUSE.'
require_line ORIGIN.md '- Preserved upstream boundary: `82d154a53f4089fecfb9f320caad826bb4f6055f`'
-printf 'PASTURESTACK_SOURCE_GATE_OK version=0.183.332 runtime_sources=github_release images=digest_pinned ubuntu=26.04 ubuntu_snapshot=20260826T000000Z jdk=25.0.4 maven=3.9.16 patched_hazelcast=5.7.5 docker_cli=29.7.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.333 runtime_sources=github_release images=digest_pinned ubuntu=26.04 ubuntu_snapshot=20260826T000000Z jdk=25.0.4 maven=3.9.16 patched_hazelcast=5.7.5 docker_cli=29.7.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 742fb4d6d0..03efc3bc38 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.332}
+expected_version=${EXPECTED_ENGINE_VERSION:-0.183.333}
test -f "$artifact"
artifact=$(realpath "$artifact")