feat: implement release authoring, so the changelog can be written
The public site has a Releases page and a footer link to the latest release, and both were empty — the read side has existed since the public surface landed, but nothing could ever create a row. The seven release operations were in the contract with no implementation, so the changelog was a page that could only ever be blank. The release model is not a blob of prose. It splits into six markdown sections because a release note answers fixed questions — why, what, what changes for a reader, what it leaves in the code, how it was verified, what is still missing — and a single text column cannot say which of those went unanswered. Publishing is the only thing that makes a release public: the public query filters on `workflow_status = 'PUBLISHED'` and nothing else. So publish is where the contract's required fields are actually enforced. Saving stays permissive — a draft you cannot save until it is complete is a draft you cannot write — and the two demands are deliberately different. `version_label` is NOT NULL UNIQUE but a draft has no version yet, so creation writes a placeholder derived from the row id and publication refuses to ship one. Relaxing the column instead would open a window where a published release is publicly visible with no version at all. A published release cannot be deleted, only archived: a public changelog entry that vanishes leaves everyone who linked it with no way to learn what happened. Also registers `adapter-outbound-objectstorage` as an app-bootstrap runtime member. It was added as a dependency when asset upload was fixed but never registered, and `verifyRuntimeModuleMembership` had not been run since.
This commit is contained in:
@@ -1363,4 +1363,43 @@ errors:
|
||||
log_level: INFO
|
||||
runbook_link: null
|
||||
compatibility_impact: additive
|
||||
required_test: ManagementErrorRegistryTest
|
||||
# source: studio-management-v1.yaml ApiError.code — RELEASE_NOT_FOUND (ManagementError.RELEASE_NOT_FOUND)
|
||||
- code: RELEASE_NOT_FOUND
|
||||
category: NOT_FOUND
|
||||
http_status: 404
|
||||
retryable: false
|
||||
retry_after_seconds: null
|
||||
owner_branch: feature-techlog-management-v1
|
||||
owner_layer: application
|
||||
client_safe_message: "요청한 릴리즈를 찾을 수 없습니다"
|
||||
log_level: INFO
|
||||
runbook_link: null
|
||||
compatibility_impact: additive
|
||||
required_test: ManagementErrorRegistryTest
|
||||
# source: studio-management-v1.yaml ApiError.code — RELEASE_VERSION_TAKEN (ManagementError.RELEASE_VERSION_TAKEN)
|
||||
- code: RELEASE_VERSION_TAKEN
|
||||
category: CONFLICT
|
||||
http_status: 409
|
||||
retryable: false
|
||||
retry_after_seconds: null
|
||||
owner_branch: feature-techlog-management-v1
|
||||
owner_layer: application
|
||||
client_safe_message: "같은 버전의 릴리즈가 이미 있습니다"
|
||||
log_level: INFO
|
||||
runbook_link: null
|
||||
compatibility_impact: additive
|
||||
required_test: ManagementErrorRegistryTest
|
||||
# source: studio-management-v1.yaml ApiError.code — RELEASE_NOT_PUBLISHABLE (ManagementError.RELEASE_NOT_PUBLISHABLE)
|
||||
- code: RELEASE_NOT_PUBLISHABLE
|
||||
category: CONFLICT
|
||||
http_status: 409
|
||||
retryable: false
|
||||
retry_after_seconds: null
|
||||
owner_branch: feature-techlog-management-v1
|
||||
owner_layer: application
|
||||
client_safe_message: "지금 상태에서는 발행할 수 없습니다"
|
||||
log_level: INFO
|
||||
runbook_link: null
|
||||
compatibility_impact: additive
|
||||
required_test: ManagementErrorRegistryTest
|
||||
Reference in New Issue
Block a user