hookdeck listen --path is not a session flag. When the value differs from what the destination already has, Listen PATCHes the destination (pkg/listen/listen.go:100-119), writing destinations.cli_path — a persisted column (server/migrations/20210327154934_destination-cli-path.ts in core). The change outlives the process and applies to every subsequent hookdeck listen on that connection, including other people's on a shared project.
That is surprising for a flag that reads like "for this run, deliver to this local path", and it is the root of several downstream constraints:
--path is rejected outright with multiple sources (pkg/listen/listen.go:57), because one flag value cannot express per-connection paths.
- It is rejected again when multiple CLI destinations resolve (
pkg/listen/listen.go:88), because we do not want to rewrite several destinations at once.
- The Console
cmd_hint bakes in --path /webhooks (server/controllers/console-test-url-response.ts:16 in core). If the user's local server does not serve /webhooks, the wrong path is persisted rather than just being wrong for one run.
The idea
Make --path a client-side forwarding rewrite instead of a destination mutation.
The CLI already has what it needs to do this per connection. The attempt message carries webhook_id (the connection id) alongside cli_path (pkg/websocket/attempt_messages.go:12-20), so the proxy knows which connection each attempt belongs to and could substitute a local path per connection when building the forward URL at pkg/listen/proxy/proxy.go:373, without touching stored config.
Reporting stays truthful
The obvious objection is that the dashboard would then show something other than where the request actually went. It would not, as long as the CLI reports the rewritten value.
server/cli/routes/attempt.ts in core takes body.cli_path off the CLI's attempt_response and publishes it as requested_url on the attempt completion. The recorded URL for a CLI attempt is whatever the CLI sends, not the stored destinations.cli_path. Today the CLI echoes the server-supplied path verbatim (pkg/listen/proxy/proxy.go:526); it would need to send the rewritten path instead.
What this would unlock
--path stops mutating shared project state, so running it is no longer something you can get wrong in a way that persists.
- The multi-source restriction can be reconsidered on its own merits rather than as a guard against multi-destination writes. A single
--path across several sources becomes a per-session default, and a per-source form (stripe=/webhooks/stripe,...) becomes expressible if we ever want it.
- The Console
cmd_hint can keep suggesting a path without the risk of leaving a wrong one behind.
Open questions
- Is anyone relying on
--path as the way to set a destination's path persistently? If so, that use case needs an explicit home — connection update / destination update already exist and are arguably the right place for it.
- Migration: changing what an existing flag does is a behaviour change. Options are a new flag, a deprecation period, or a major-version change.
requested_url is published as just the path today, since that is what the CLI sends. Worth confirming how the dashboard renders it before relying on it to carry the rewrite.
Relationship to #371
Split out of #371, which is about the multi-source panic and silent drop. That issue can be fixed without any of this. This one is the larger question behind the --path restrictions it runs into.
hookdeck listen --pathis not a session flag. When the value differs from what the destination already has,ListenPATCHes the destination (pkg/listen/listen.go:100-119), writingdestinations.cli_path— a persisted column (server/migrations/20210327154934_destination-cli-path.tsincore). The change outlives the process and applies to every subsequenthookdeck listenon that connection, including other people's on a shared project.That is surprising for a flag that reads like "for this run, deliver to this local path", and it is the root of several downstream constraints:
--pathis rejected outright with multiple sources (pkg/listen/listen.go:57), because one flag value cannot express per-connection paths.pkg/listen/listen.go:88), because we do not want to rewrite several destinations at once.cmd_hintbakes in--path /webhooks(server/controllers/console-test-url-response.ts:16incore). If the user's local server does not serve/webhooks, the wrong path is persisted rather than just being wrong for one run.The idea
Make
--patha client-side forwarding rewrite instead of a destination mutation.The CLI already has what it needs to do this per connection. The attempt message carries
webhook_id(the connection id) alongsidecli_path(pkg/websocket/attempt_messages.go:12-20), so the proxy knows which connection each attempt belongs to and could substitute a local path per connection when building the forward URL atpkg/listen/proxy/proxy.go:373, without touching stored config.Reporting stays truthful
The obvious objection is that the dashboard would then show something other than where the request actually went. It would not, as long as the CLI reports the rewritten value.
server/cli/routes/attempt.tsincoretakesbody.cli_pathoff the CLI'sattempt_responseand publishes it asrequested_urlon the attempt completion. The recorded URL for a CLI attempt is whatever the CLI sends, not the storeddestinations.cli_path. Today the CLI echoes the server-supplied path verbatim (pkg/listen/proxy/proxy.go:526); it would need to send the rewritten path instead.What this would unlock
--pathstops mutating shared project state, so running it is no longer something you can get wrong in a way that persists.--pathacross several sources becomes a per-session default, and a per-source form (stripe=/webhooks/stripe,...) becomes expressible if we ever want it.cmd_hintcan keep suggesting a path without the risk of leaving a wrong one behind.Open questions
--pathas the way to set a destination's path persistently? If so, that use case needs an explicit home —connection update/destination updatealready exist and are arguably the right place for it.requested_urlis published as just the path today, since that is what the CLI sends. Worth confirming how the dashboard renders it before relying on it to carry the rewrite.Relationship to #371
Split out of #371, which is about the multi-source panic and silent drop. That issue can be fixed without any of this. This one is the larger question behind the
--pathrestrictions it runs into.