mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-11-02 09:23:59 +00:00
b1e8ac469b
* fix(webhooks): whole-workspace access to manage them; none for a deleted workspace (BUG-3340)
A webhook receives item snapshots from every collection, but creating or
test-firing one required only the owner role, so an owner restricted to
specific collections could route every collection's content to a URL of
their choosing. Create and test now require unrestricted workspace
access, through the same check full export uses (BUG-1922), factored
into requireUnrestrictedAccess. Delete stays open: it is revocation.
ListWebhooks now returns nothing for a soft-deleted workspace. Both
dispatcher delivery paths (Dispatch and DeliverEvent) list through it,
so a deleted workspace's events are dropped instead of delivered during
the restore window; a restore brings the webhooks back.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(webhooks): re-check the workspace before every send; hide URLs from restricted owners (BUG-3340)
Codex r1 (no P0):
- P1: ListWebhooks checked deletion once, but a delivery reuses the hook
list and payload across inline retries, later hooks in the fan-out,
and redirect hops; codex reproduced POSTs after the delete committed.
The dispatcher store gains WorkspaceLive, checked before every attempt
(a new deliverySuppressed result: nothing sent, not the endpoint's
failure, not counted as matched) and before every redirect hop (the
request carries the hook's workspace). A lookup error is transient, so
a blip delays rather than drops or sends unchecked.
- P2: the list still showed restricted owners every destination URL, and
a URL can be the credential to a receiver's stored request bodies. A
restricted owner now sees each webhook without its URL (the id is
kept, so they can still delete it).
Tests: retry, later hook and redirect after a mid-delivery deletion each
send nothing (all three red with the checks disabled); the list hides
URLs from the restricted owner only.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(webhooks): check the workspace on every connection; defer on lookup errors (BUG-3340)
Codex r2 (no P0):
- P1: net/http can send more than once inside one Do (it re-dials and
replays the body after a reused connection fails with nothing
written), and a deletion can land during dial or TLS setup, both after
the per-attempt check. An httptrace GotConn hook now re-checks the
workspace on every connection the request is about to be written on,
after TLS and before writing, and cancels the request if it is gone.
- P2 (two): a liveness lookup ERROR was treated as a deletion at the
redirect check (the outbox then acked an undelivered event) and as an
endpoint failure before a send (charged to the hook, which could
auto-deactivate it). A new deliveryDeferred result sends nothing, keeps
the event owed (Transient, so the outbox does not ack), and charges
nothing to the hook. Suppression is reserved for a confirmed deletion.
Tests: deletion before the connection is ready sends nothing; a
pre-send lookup error and a redirect lookup error each defer without
sending or charging. Each goes red when its own fix is reverted.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(webhooks): close the connection in GotConn, a real write barrier (BUG-3340)
Codex r3 (no P0/P2): cancelling the request context in GotConn is not a
write barrier for HTTP/1: the transport queues the request before it
checks the context, so its writer could still send the whole request
(codex measured 10/10,000 in the zero-send test). GotConn now also closes
the connection it was handed when the workspace is gone or its liveness
unknown: nothing can be written to a closed socket, and the cancel stops
any transport retry on a fresh one.
Measured here: the cancel-only version fails the zero-send test 2/10,000;
with the close, 0/10,000 for both the deletion and lookup-error tests,
and the webhooks package passes under -race.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(webhooks): the connection check decides the outcome even if Do returns a response (BUG-3340)
Codex r4 (no P0/P1) P2: after GotConn closes and cancels, net/http can
still return an already-buffered response, and the suppressed/deferred
flags were only consulted when Do returned an error, so such a response
counted as a delivery. The flags are now checked right after Do,
whatever it returned, closing any response body first.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 7ee0bddc45)