mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-27 22:34:51 -06:00
refactor(routes): wire DELETE on path-keyed workstreams/{ws_id}/send
Pre-flight for the legacy URL adapter removal: the path-keyed
`/v1/api/workstreams/{ws_id}/send` route only mounted POST today;
the dequeue handler was reachable only via the legacy
`DELETE /v1/api/send` body-keyed URL through `_make_method_dispatch`.
Add a new `dequeue: Handler | None = None` slot on
`SharedSessionVerbHandlers` next to `send`, mounted as a second
`Route` on the same path with `methods=["DELETE"]` (two distinct
Routes rather than collapsing methods on one Route — different
handler callables, and collapsing would force the same
method-dispatch wrapper this cleanup is tearing out).
Wire `dequeue=dequeue_handler` in `turnstone/server.py`'s
`SharedSessionVerbHandlers(...)` call so DELETE on the path-keyed
shape works in the same merge as the legacy mount removal.
Adds a regression-locking test covering both the POST+DELETE and
the dequeue-alone cases.
This commit is contained in:
@@ -119,6 +119,34 @@ def test_attachment_routes_mount_when_quartet_provided() -> None:
|
||||
) in paths
|
||||
|
||||
|
||||
def test_send_mounts_post_and_delete_when_dequeue_provided() -> None:
|
||||
"""``handlers.send`` mounts POST {prefix}/{ws_id}/send and
|
||||
``handlers.dequeue`` mounts DELETE on the same path. The two
|
||||
routes register as separate ``Route`` entries with disjoint
|
||||
method sets — Starlette dispatches by (path, method)."""
|
||||
routes: list[Any] = []
|
||||
register_session_routes(
|
||||
routes,
|
||||
prefix="/api/workstreams",
|
||||
handlers=SharedSessionVerbHandlers(send=_stub, dequeue=_stub),
|
||||
)
|
||||
paths = {(p, m) for p, m in _route_paths(routes)}
|
||||
assert ("/api/workstreams/{ws_id}/send", frozenset({"POST"})) in paths
|
||||
assert ("/api/workstreams/{ws_id}/send", frozenset({"DELETE"})) in paths
|
||||
|
||||
# ``dequeue`` is independent of ``send`` — providing it alone
|
||||
# mounts only the DELETE half (no POST regression).
|
||||
routes_dequeue_only: list[Any] = []
|
||||
register_session_routes(
|
||||
routes_dequeue_only,
|
||||
prefix="/api/workstreams",
|
||||
handlers=SharedSessionVerbHandlers(dequeue=_stub),
|
||||
)
|
||||
paths_dequeue_only = {(p, m) for p, m in _route_paths(routes_dequeue_only)}
|
||||
assert ("/api/workstreams/{ws_id}/send", frozenset({"DELETE"})) in paths_dequeue_only
|
||||
assert ("/api/workstreams/{ws_id}/send", frozenset({"POST"})) not in paths_dequeue_only
|
||||
|
||||
|
||||
def test_close_legacy_mounts_when_handler_provided() -> None:
|
||||
"""The legacy body-keyed close (``POST {prefix}/close``) mounts
|
||||
when ``handlers.close_legacy`` is non-``None`` — there is no
|
||||
|
||||
@@ -482,6 +482,7 @@ class SharedSessionVerbHandlers:
|
||||
# Per-``{ws_id}`` interaction (coord shape today; interactive
|
||||
# adopts these in Priority 1's worker dispatch unification)
|
||||
send: Handler | None = None # POST {prefix}/{ws_id}/send
|
||||
dequeue: Handler | None = None # DELETE {prefix}/{ws_id}/send
|
||||
approve: Handler | None = None # POST {prefix}/{ws_id}/approve
|
||||
plan: Handler | None = None # POST {prefix}/{ws_id}/plan
|
||||
cancel: Handler | None = None # POST {prefix}/{ws_id}/cancel
|
||||
@@ -566,6 +567,8 @@ def register_session_routes(
|
||||
routes.append(Route(f"{p}/{{ws_id}}/title", handlers.set_title, methods=["POST"]))
|
||||
if handlers.send is not None:
|
||||
routes.append(Route(f"{p}/{{ws_id}}/send", handlers.send, methods=["POST"]))
|
||||
if handlers.dequeue is not None:
|
||||
routes.append(Route(f"{p}/{{ws_id}}/send", handlers.dequeue, methods=["DELETE"]))
|
||||
if handlers.approve is not None:
|
||||
routes.append(Route(f"{p}/{{ws_id}}/approve", handlers.approve, methods=["POST"]))
|
||||
if handlers.plan is not None:
|
||||
|
||||
@@ -3556,6 +3556,7 @@ def create_app(
|
||||
refresh_title=refresh_workstream_title,
|
||||
set_title=set_workstream_title,
|
||||
send=send_handler, # lifted: shared body (P1.5)
|
||||
dequeue=dequeue_handler, # lifted (P1.5) — DELETE /send
|
||||
approve=approve_handler, # lifted: shared body
|
||||
cancel=cancel_handler, # lifted: shared body
|
||||
events=events_handler, # lifted: shared body
|
||||
|
||||
Reference in New Issue
Block a user