Repository navigation
Conversation
Apply Kong/volcano-hosting#2364's change to the bundled public spec (docs/public/api-reference/openapi.yaml, 82a97eb58c..6377c22be0) and regenerate the client with scripts/generate_openapi.py. Only that delta is taken; the rest of Hosting's drift stays with the automated sync PR.
Add durable.get_from_application and durable.stop_from_application. They call the data-plane routes from Kong/volcano-hosting#2364 with the credential start uses, and send the execution's client token as X-Volcano-Client-Token when given. The owner-scoped get, list and stop are unchanged. Share the messages facade's header check through _durable_arguments, and stop saying in docstrings and docs that reading or stopping needs the owner's token.
Copy the start path, the two application execution paths, the DurableClientToken parameter and the DurableExecution schema from Hosting main 1ccff82a16's public bundle, and regenerate the client. Hosting #2364 shipped scoped service keys: only a key holding `*` reaches any execution, including a pending one; a key scoped without `*` needs the execution's client token. Say so in the facade docstrings, README and docs, and note that a ServerError from a stop can follow a stop already sent. Pin that the client token goes out with every credential over the wire, including a service key.
AI review: no P0-P2 findingsThis PR adds Not checked: The AI review read the diff, the code, and the PR's text; it ran no tests or builds and read nothing outside this repository.
Human review: needed
The AI review found no P0-P2 problems at 8bbda67, so the code needs no second review for bugs. Decide the points above: approve to accept them, or request changes. Suggested reviewer: |
swkeever
left a comment
There was a problem hiding this comment.
Guided review of 5d3cdd4.
1. Should execution client tokens used for messaging also authorize result access and cancellation through the new methods?
Accept. Hosting's shipped contract (main at a525bc6477, from #2364) makes the client token one per-execution credential for reading, stopping, and messaging. DurableExecution.client_token in api/openapi.yaml says it lets a browser read the execution, stop it, and read and send its messages, and lets a scoped service key read and stop it; durable-functions.md and durable-messages.md say the same. The server enforces this, not the SDK: in internal/handlers/durable_application_access.go, the read, stop, and messages routes all clear the caller through clearDurableApplicationRequest and Target.Admits, and read and stop differ from messages only in requiring the token from a service key scoped without *. These methods only forward X-Volcano-Client-Token, and the copied spec sections are identical to Hosting's public bundle at a525bc6477.
Docstring fix (non-blocking): see the suggestion on get_from_application. "Anything else raises NotFoundError" leaves out the visibility check that docs/functions.md states. For example, an anon key with the token on an authenticated function raises PermissionDeniedError.
Parity fix (non-blocking follow-up): JS (Kong/volcano-sdk-js#357) exposes the throttled 503's Retry-After as error.retryAfter. Python and Ruby (Kong/volcano-sdk-ruby#366) read Retry-After only on a 429. Reading it on a 503 as well, in response_payload in _transport_response.py and in Ruby's Transport, would set ServerError.retry_after and close the gap.
Generated by the guided-review skill. Install it with one command:
sh -c 'd=$(mktemp -d) && gh repo clone Kong/volcano-conventions "$d" -- --depth 1 -q && make -C "$d" install-skills guided-review pr-review explain-pr; s=$?; rm -rf "$d"; exit $s'Then ask your coding agent for a guided review of a PR or issue URL. Run the command again to update.
…ication reads A visibility refusal raises PermissionDeniedError rather than NotFoundError, and a service key scoped without * also needs functions.invoke.
A private function answers every credential but a service key with 404, so it raises NotFoundError. Only a missing functions.invoke or an anonymous key on an authenticated function raises PermissionDeniedError.
Change
A Python application can now read and stop the durable executions it started, with the credential
start()already uses: the active session, then a service key, then the anon key. Before this,get()andstop()called only the owner routes, which need a platform token.GET /durable-functions/{functionId}/executions/{executionId}andPOST .../stop.client_tokengoes out asX-Volcano-Client-Tokenwhen given and is omitted otherwise. It is checked the waydurable.messageschecks it: a non-empty printable ASCII string with no surrounding whitespace, at most 128 characters.client_tokengoes out with every credential, including a service key: a service key scoped without*reaches an execution only with its token. A key holding*, the default, reaches any execution, including apendingone.NotFoundError, which is also what a credential that cannot reach the execution gets. A 409 on a stop raisesConflictError, and only a service key holding*gets it.ServerError. The SDK readsRetry-Afteronly on a 429 (RateLimitedError.retry_after), so the header a throttled read sends with its 503 is not surfaced. The docs say aServerErrorfrom a stop can follow a stop that was already sent, so read before stopping again.get(),list()andstop()are unchanged. These no longer say that reading or stopping needs the owner's token: their docstrings, thestart()docstring, theDurableExecution.client_tokencomment,docs/functions.mdand the README._durable_messagesto_durable_arguments.header_value, so both facades share it. Its behavior is unchanged.Depends on Kong/volcano-hosting#2364, merged as
29807384cf.Coordination branch:
skeever/durable-execution-data-plane.Contract snapshot
openapi/openapi.yamltakes only the durable sections #2364 shipped: the start path, the two application paths, theDurableClientTokenparameter, and theDurableExecutionschema. They are copied verbatim from the public bundlescripts/ci/openapi-bundle.shbuilds from Hosting main1ccff82a16, which equals itsdocs/public/api-reference/openapi.yaml, and now match it exactly. The rest of Hosting's drift is left to the automated sync PR (#2). The client was regenerated withuv run python scripts/generate_openapi.py. The generator's required-operation list adds the two new operations.Verification
On
5d3cdd4, with uv 0.12.17, the version CI pins:poe policy,generated,lint,format-check,types(mypy and basedpyright),audit,package-check: pass.poe testandpoe coverage: 3,042 passed, 1 failed; coverage 100%. The failure istest_realtime.py::test_realtime_presence_sync_coalesces_latest_backpressured_state, a 0.2 s timing assertion this PR does not touch, which fails intermittently on this machine at load average ~58 and passed in CI on61fbf9c.poe mutation, run per changed module on61fbf9c, left no survivors.5d3cdd4changes only docstrings, docs, the spec text, and tests, so it is left to CI's per-module mutation jobs:durable_durable_messages_transport_execution_durable_argumentsmodelschanged only in a comment.New tests in
src/volcano_sdk/_tests/test_durable.pycover:Authorizationthrough the generated transport over a mock HTTP transport, withX-Volcano-Client-Tokensent when given and absent when not;X-Volcano-Client-Tokensent over the wire with a session, a service key, and an anon key;Deferred to CI:
package-extras(tox). Not run: cloud E2E and the live staging sdk-contract runner.Cross-language impact
Classification: public facade and wire contract.
tests/sdk-contracthas no requirement for reading or stopping from an application. A shared scenario belongs in the coordinated Hosting change.getFromApplication,stopFromApplication) is on the same branch name in Kong/volcano-sdk-js; it had no PR when this one opened.README.mdanddocs/functions.md.Coordination
Companion PRs, all on
skeever/durable-execution-data-plane: Kong/volcano-sdk-js#357, #422, Kong/volcano-sdk-ruby#366.Merge order:
tests/sdk-contractscenarios for both routes.🤖 Generated with Claude Code