fix(studio-save): 확인 없이 옮긴 문장을 고치고, 안 닿는 가지에 유효 범위를 적는다
「Decision 은 계약에 삭제 경로가 없다」고 적었는데 틀렸다. ManagementDocumentController
:123 에 DELETE /v1/studio/projects/{id}/decisions/{decisionId} 가 있다. 스킬의 문장을
확인 없이 옮겼다. 시험 초안을 CASE 로 고른 이유는 삭제 경로 때문이 아니라 그 기록이 이
배치가 만든 것이라 남의 것이 아니어서다.
멱등 키 길이 검사는 지금 정책에서 안 닿는다. 키가 studio-{op}-{32자}(+{32자})라 길이가
사실상 고정이고 저장 키가 77자다. 죽은 코드가 아니라 키 정책이 바뀌면 살아나는 방어선이라
지우지 않고, 언제 살아나는지를 주석에 적었다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
This commit is contained in:
co-authored by
Claude Opus 5
parent
c66eee6cb2
commit
4e9226a57d
@@ -178,6 +178,9 @@ def idempotency_key(op: str, record_rel: str, payload: dict | None = None) -> st
|
|||||||
key = f"studio-{op}-{base}"
|
key = f"studio-{op}-{base}"
|
||||||
if payload is not None:
|
if payload is not None:
|
||||||
key += "-" + _sha256_text(json.dumps(payload, ensure_ascii=False, sort_keys=True))[:32]
|
key += "-" + _sha256_text(json.dumps(payload, ensure_ascii=False, sort_keys=True))[:32]
|
||||||
|
# **지금 키 정책에서는 여기 안 온다.** 키가 `studio-{op}-{32자}`(+`-{32자}`)라 길이가
|
||||||
|
# 사실상 고정이고 저장 키가 77자다. 죽은 코드가 아니라 **키 정책이 바뀌면 그때 살아나는
|
||||||
|
# 방어선**이다 — 경로를 키에 그대로 넣는 식으로 바꾸면 200자를 넘길 수 있다. 지우지 않는다.
|
||||||
if len(key) > MAX_KEY_LENGTH: # 서버가 200자 초과를 거절한다
|
if len(key) > MAX_KEY_LENGTH: # 서버가 200자 초과를 거절한다
|
||||||
raise Refused(f"멱등 키가 {len(key)}자다. 서버 상한은 {MAX_KEY_LENGTH}자")
|
raise Refused(f"멱등 키가 {len(key)}자다. 서버 상한은 {MAX_KEY_LENGTH}자")
|
||||||
return key
|
return key
|
||||||
@@ -492,7 +495,11 @@ def plan_requests(record_path: str, doc: dict, document_id: str | None,
|
|||||||
#
|
#
|
||||||
# `DELETE /api/v1/studio/cases/{id}` 는 실재한다
|
# `DELETE /api/v1/studio/cases/{id}` 는 실재한다
|
||||||
# (`ManagementDocumentController.java:72` · `studio-management-v1.yaml:126,246`).
|
# (`ManagementDocumentController.java:72` · `studio-management-v1.yaml:126,246`).
|
||||||
# 종류를 CASE 로 고른 이유가 그것이다 — Decision 은 계약에 삭제 경로가 없다.
|
#
|
||||||
|
# **시험 초안을 CASE 로 고른 이유는 삭제 경로 때문이 아니다.** 처음에 「Decision 은
|
||||||
|
# 계약에 삭제 경로가 없다」고 적었는데 틀렸다 — `ManagementDocumentController.java:123`
|
||||||
|
# 에 `DELETE /v1/studio/projects/{id}/decisions/{decisionId}` 가 있다. 스킬의 문장을
|
||||||
|
# 확인 없이 옮겼다. **고른 이유는 그 기록이 이 배치가 만든 것이라 남의 것이 아니어서다.**
|
||||||
steps.append({
|
steps.append({
|
||||||
"op": "cleanup", "method": "DELETE",
|
"op": "cleanup", "method": "DELETE",
|
||||||
"path": f"/api/v1/studio/cases/{document_id or '<생성된 id>'}",
|
"path": f"/api/v1/studio/cases/{document_id or '<생성된 id>'}",
|
||||||
|
|||||||
@@ -504,8 +504,11 @@ class HarnessTestPlanTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_the_cleanup_path_is_the_case_delete_endpoint(self):
|
def test_the_cleanup_path_is_the_case_delete_endpoint(self):
|
||||||
"""`DELETE /api/v1/studio/cases/{id}` 는 실재한다
|
"""`DELETE /api/v1/studio/cases/{id}` 는 실재한다
|
||||||
(`ManagementDocumentController.java:72`). Decision 은 삭제 경로가 없어서
|
(`ManagementDocumentController.java:72`).
|
||||||
시험 초안의 종류를 CASE 로 고른다."""
|
|
||||||
|
시험 초안을 CASE 로 고른 이유는 삭제 경로 때문이 아니다 — Decision 에도
|
||||||
|
`DELETE /v1/studio/projects/{id}/decisions/{decisionId}` 가 있다(`:123`).
|
||||||
|
고른 이유는 그 기록이 이 배치가 만든 것이라 남의 것이 아니어서다."""
|
||||||
steps = ss.plan_requests("docs/p/t/case/x.md", dict(SENT), None, None,
|
steps = ss.plan_requests("docs/p/t/case/x.md", dict(SENT), None, None,
|
||||||
harness_test=True)
|
harness_test=True)
|
||||||
cleanup = next(s for s in steps if s["op"] == "cleanup")
|
cleanup = next(s for s in steps if s["op"] == "cleanup")
|
||||||
|
|||||||
Reference in New Issue
Block a user