Repository navigation
API: publish, unpublish and delete go through the table action service (#2569) - #2588
Merged
Merged
Conversation
#2569) The single-table endpoints move_publish/<topic>/, unpublish/ and the table DELETE call api.services.table_actions, the path the tables tab takes, instead of a second one. Request and response bodies stay as they were ({} / {"reason": ...}) and the committed openapi.yaml is unchanged. - Publishing is atomic: an unknown topic no longer sets the embargo and moves peer reviews before failing. `draft` is refused as a topic, and an embargo duration other than none/6_months/1_year is a 400 instead of being ignored. - What the API always did still holds: a published table is published again under another topic (`republish`), an omitted embargo leaves the existing one (`KEEP_EMBARGO`), unpublishing a draft is a 200, and a published table is deleted without the dashboard's typed confirmation (the address names it). - Delete runs outside any transaction (the service's is durable). A failed OEDB drop after the record is gone answers 500 naming the table. - Refusals map onto the API's existing answers: a role lost under the lock is 403, a table gone is 404, anything else 400 naming the reason. - Every action logs `table_action ... via=api`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2569. Slice 17 of spec #2551.
The single-table API endpoints for publish (
tables/<t>/move_publish/<topic>/), unpublish (tables/<t>/unpublish/) and delete (DELETE tables/<t>/) now callapi/services/table_actions.py, the same path the tables tab's ⋯ menu uses. There is no second path. Request and response bodies stay as they were ({}, or{"reason": …}on a refusal). The committedopenapi.yamlis unchanged (api.tests.test_openapi_schemagreen, no regeneration).What changes for API clients
draftis refused as a topic (400). Before, it published under the pseudo-topic.table_action … via=apiline onoeplatform.table_actions.All of this is in the changelog under "Changes".
What deliberately does not change
The issue's acceptance criterion "existing API tests stay green" decides these.
TestMovePublishpublishes the same table twice and expects 200 both times.republish=True. The dashboard view never forwards it (itsPARAMSwhitelist), so the bulk rule is untouched.move_publishalways did. The service's default isnone, which lifts an embargo. Applied to the API, that would have silently ended an embargo on any re-publish that didn't repeat it. New valueKEEP_EMBARGO = "keep", sent only by the API._done_messagetolerates it.confirm. That is exactly what the dialog asks for one published table. Whether the API should guard this is out of scope (spec, "Not changed").How refusals map
table_action()inapi/views.py:InvalidParametersActionRefusedwith a role reasonActionRefused"Not one of your tables", table goneActionRefused"Not one of your tables", table thereActionRefusedThe decorators have already checked existence and role, so the first three only happen if something changed between that check and the service's row lock.
Delete and transactions
The service runs delete in a durable transaction, so it refuses to run nested. The view opens no atomic block, and
ATOMIC_REQUESTSis set nowhere.test_the_view_does_not_run_the_service_inside_a_transactionchecks this directly: Django'sTestCasedisables the durability check, so the test looks for any atomic block that isn't the test case's own.Table.delete()stays for its other callers.Tests
api/tests/test_table_actions_api.py, 20 tests through the test client over the real endpoints:via=apilog lineExisting
TestMovePublish,TestDelete,test_publish_gateandtest_modification_stampsare green. So are the dashboard'slogin.tests.test_table_actions,test_table_deleteandtest_table_dataset_actions(84). Full suite: 1,370 tests, the only failure the knownLightImportTestunder isolated settings, which passes on its own. It ran against a private OEDB built withalembic upgrade head, because two other sessions' runs were deadlocked in the shared sandbox.No migration, no deploy step. No UI in this slice.
Open points for the maintainer
republishandKEEP_EMBARGOare API-only behaviours inside the shared service. I chose explicit parameters over a check onvia=, so the rule reads off the call. The alternative was to refuse re-publish via the API too. That breaksTestMovePublishand removes the API's only way to add a topic or change an embargo.openapi.yamldoesn't declare. Declaring it would change the artifact, which this slice must not do. Before, the same case was an undeclared 400._check; the merged result keeps both.🤖 Generated with Claude Code