feat: serve uploaded media, delete a decision, and stop orphaning publications
Three gaps that all showed up as something broken on screen. An uploaded image could never be fetched. Every asset address the backend builds pointed at a path nothing served, so a figure was missing in the Studio preview and in the published page alike. There is now a public media endpoint under the prefix that is already anonymous and already routed, so no edge configuration has to change for an image to appear. Only READY assets are served; narrowing it to assets a published record uses would break previewing, which is the one thing an author does before publishing. Deleting a working copy left wreckage. Publications, validations and previews address a document by (kind, id) with no foreign key, so deleting one left rows pointing at nothing — and the dashboard and publication history read a title off that nothing and crashed. Both screens went down in production this way. A record with publication history is now refused outright, because that history says what was once public; validations and previews go with the record, because they are its scaffolding. A Decision could not be deleted at all while every other kind could. It can now, under the same two rules, and refuses when another decision supersedes it or the home page features it — neither cascades, so deleting would have been a foreign-key violation reaching the author as a 500. The persistence tests cover every one of these queries against real PostgreSQL. That suite exists because a column name I assumed rather than checked reached production once already; three more assumptions were caught here before it could happen again.
This commit is contained in:
@@ -1467,4 +1467,30 @@ errors:
|
||||
log_level: INFO
|
||||
runbook_link: null
|
||||
compatibility_impact: additive
|
||||
required_test: ManagementErrorRegistryTest
|
||||
# source: studio-management-v1.yaml ApiError.code — DECISION_NOT_FOUND (ManagementError.DECISION_NOT_FOUND)
|
||||
- code: DECISION_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 — DECISION_IN_USE (ManagementError.DECISION_IN_USE)
|
||||
- code: DECISION_IN_USE
|
||||
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