diff --git a/CHANGELOG.md b/CHANGELOG.md index f543719..3499e82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.3.12] - 2026-09-20 + +### Fixed + +- Make `operator` optional for encoded-key item deletion so user tokens can use the token owner, matching ordinary-key deletion. Consumer tokens still require an explicit operator. + ## [0.3.11] - 2026-08-28 ### Added diff --git a/apollo-openapi.yaml b/apollo-openapi.yaml index 45f420b..90a7757 100644 --- a/apollo-openapi.yaml +++ b/apollo-openapi.yaml @@ -18,7 +18,7 @@ info:
curl -X GET "http://localhost:8070/openapi/v1/apps" \
-H "Authorization: your_token_here"
- version: 0.3.11
+ version: 0.3.12
security:
- ApiKeyAuth: []
tags:
@@ -1336,8 +1336,8 @@ paths:
type: string
- name: operator
in: query
- description: ''
- required: true
+ description: 操作人用户名;user-token 模式使用 token 所属用户,consumer-token 模式必须提供
+ required: false
schema:
type: string
responses:
diff --git a/tests/test_user_token_contract.py b/tests/test_user_token_contract.py
index 9805471..9f67690 100644
--- a/tests/test_user_token_contract.py
+++ b/tests/test_user_token_contract.py
@@ -17,6 +17,20 @@ def setUp(self):
def _load_spec(self, spec_file):
return yaml.safe_load((self.repo_root / spec_file).read_text(encoding="utf-8"))
+ def test_plain_and_encoded_item_delete_allow_token_owner_as_operator(self):
+ for spec_file in SPEC_FILES:
+ spec = self._load_spec(spec_file)
+ for resource in ("items", "encodedItems"):
+ path = ("/openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}"
+ "/namespaces/{namespaceName}/" + resource + "/{key}")
+ with self.subTest(spec=spec_file, resource=resource):
+ operation = spec["paths"][path]["delete"]
+ operator = next(parameter for parameter in operation["parameters"]
+ if parameter["name"] == "operator")
+ self.assertEqual("query", operator["in"])
+ self.assertFalse(operator.get("required", False))
+ self.assertEqual("string", operator["schema"]["type"])
+
def test_user_token_management_paths_use_generated_contract(self):
for spec_file in SPEC_FILES:
spec = self._load_spec(spec_file)