bend-kit-webhooks Releases (13): 0.11.0.1 0x78015a10d993786d85ee4044e876ee92 indexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.11.0.1 0.11.0.0 0x7020350ecbcf4843b197b17280169db4 unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.11.0.0 0.10.0.0 0xd3a1ac0a670047ccccda2148369267f0 unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.10.0.0 0.9.0.0 0x8056f1dcda85933450c419f5ccfe6f13 unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.9.0.0 0.8.0.0 0xa8c8c9d8c3e04904c61a613f926a35c0 unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.8.0.0 0.7.0.0 0x4cb3232f7d188b565aa061ff4a63f466 unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.7.0.0 0.6.0.0 0x3214da5592d0ad257bde05319985e9e0 unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.6.0.0 0.5.0.0 0xcfe06f516d6670353eac1eb2e94880f9 unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.5.0.0 0.4.0.0 0x4a7d973e4ae0bafb3dcb7a14562a9b95 unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.4.0.0 0.3.0.1 0x32891545eb90c278cde451b4ec2b680f unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.3.0.1 0.3.0.0 0x3fbad038cfeb527d82e8b4d1174a21a5 unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.3.0.0 0.2.0.0 0xf2e81b9be1321540335cf99dc4e973ba unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.2.0.0 0.1.0.0 0x47370f6eaec04e4f1aa9598b3d00e3f0 unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-webhooks@0.1.0.0 Definitions (71): Webhooks.Err (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=Err) type Err is Data: Missing{name: String} BadSecret{} BadId{} BadTimestamp{} TooOld{} TooNew{} NoMatch{} CryptoErr{code: U32, msg: String} Webhooks.field.head (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=field.head) def field.head(xs: List<&2, String>) -> Maybe<&2, String>: Webhooks.field.of (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=field.of) def field.of(r: Map<&2, List<&2, String>> & List<&2, String>) -> Maybe<&2, String>: Webhooks.field (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=field) def field(+h: Map<&2, List<&2, String>>, k: String) -> Maybe<&2, String>: Webhooks.need (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=need) def need(+name: String, m: Maybe<&2, String>) -> Result<&1, &1, Err, String>: Webhooks.strip (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=strip) # s after the prefix p, or None. def strip(+p: String, +s: String) -> Maybe<&2, String>: Webhooks.push (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=push) def push(m: Maybe<&2, String>, rest: List<&2, String>) -> List<&2, String>: Webhooks.put (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=put) def put(m: Map<&2, List<&2, String>>, k: String, v: String) -> Map<&2, List<&2, String>>: Webhooks.digits (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=digits) def digits(s: String) -> Bool: Webhooks.ts.some (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=ts.some) def ts.some(ok: Bool, m: Maybe<&2, Int.I64>) -> Result<&1, &1, Err, Int.I64>: Webhooks.ts.read (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=ts.read) # Unix seconds: 1 to 18 ASCII digits, no sign, so the parse never overflows. def ts.read(+s: String) -> Result<&1, &1, Err, Int.I64>: Webhooks.window.pick (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=window.pick) def window.pick(old: Bool, ahead: Bool) -> Result<&1, &1, Err, Unit>: Webhooks.window (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=window) # t within tol seconds of now, either way. def window(+tol: U32, now: Time.Instant, t: Int.I64) -> Result<&1, &1, Err, Unit>: Webhooks.id.check (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=id.check) # A webhook id is not empty and has no '.', so id.timestamp.body reads one way. def id.check(+id: String) -> Result<&1, &1, Err, Unit>: Webhooks.b64.same (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=b64.same) def b64.same(+s: String, r: Bytes.Bytes & Bytes.Bytes) -> Maybe<&1, Bytes.Bytes>: Webhooks.b64.canon (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=b64.canon) def b64.canon(+s: String, m: Maybe<&1, Bytes.Bytes>) -> Maybe<&1, Bytes.Bytes>: Webhooks.b64 (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=b64) # Padded standard base64, only in its canonical text: Bytes.from_base64 alone accepts nonzero pad bits. def b64(+s: String) -> Maybe<&1, Bytes.Bytes>: Webhooks.pad (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=pad) # '=' up to a multiple of four chars. def pad(+s: String) -> String: Webhooks.nonempty.of (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=nonempty.of) def nonempty.of(b: Bytes.Bytes) -> Maybe<&1, Bytes.Bytes>: Webhooks.nonempty (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=nonempty) def nonempty(m: Maybe<&1, Bytes.Bytes>) -> Maybe<&1, Bytes.Bytes>: Webhooks.key.std (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=key.std) # A Standard Webhooks secret: whsec_ then base64 of the key, padded or not. The prefix is optional. def key.std(+s: String) -> Maybe<&1, Bytes.Bytes>: Webhooks.key (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=key) # std: a Standard Webhooks secret. Otherwise the secret's UTF-8 is the key, as Stripe and GitHub use it. def key(+std: Bool, +s: String) -> Maybe<&1, Bytes.Bytes>: Webhooks.decode (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=decode) # A signature's octets: hex (Stripe, GitHub) or canonical base64 (Standard Webhooks). def decode(+hex: Bool, +s: String) -> Maybe<&1, Bytes.Bytes>: Webhooks.mac.of (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=mac.of) def mac.of(r: Result<&1, &1, U32 & String, U32 & Array>) -> Result<&1, &1, Err, Bytes.Bytes>: Webhooks.mac (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=mac) def mac(k: Bytes.Bytes, data: Bytes.Bytes) -> IO(Result<&1, &1, Err, Bytes.Bytes>): Webhooks.ct.go (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=ct.go) def ct.go(m: Bytes.Bytes, s: Bytes.Bytes) -> IO(Bool): Webhooks.ct (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=ct) # A signature that does not decode matches nothing. def ct(s: Maybe<&1, Bytes.Bytes>, m: Bytes.Bytes) -> IO(Bool): Webhooks.any.sig (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=any.sig) # Does any signature equal the MAC? r holds the MAC and a copy; every signature is compared. def any.sig(sigs: List<&2, String>, +hex: Bool, r: Bytes.Bytes & Bytes.Bytes) -> IO(Bool): Webhooks.key.cmp (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=key.cmp) def key.cmp(r: Result<&1, &1, Err, Bytes.Bytes>, +hex: Bool, +sigs: List<&2, String>) -> IO(Result<&1, &1, Err, Bool>): Webhooks.key.check (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=key.check) def key.check(k: Maybe<&1, Bytes.Bytes>, +hex: Bool, +sigs: List<&2, String>, msg: Bytes.Bytes) -> IO(Result<&1, &1, Err, Bool>): Webhooks.both.done (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=both.done) def both.done(+x: Bool, b: Result<&1, &1, Err, Bool>) -> Result<&1, &1, Err, Bool>: Webhooks.both (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=both) # A bad secret fails the check, even when another secret matches. def both(a: Result<&1, &1, Err, Bool>, b: Result<&1, &1, Err, Bool>) -> Result<&1, &1, Err, Bool>: Webhooks.any.key (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=any.key) # Does any signature sign the message under any secret? r holds the message and a copy. def any.key(keys: List<&2, String>, +std: Bool, +hex: Bool, +sigs: List<&2, String>, r: Bytes.Bytes & Bytes.Bytes) -> IO(Result<&1, &1, Err, Bool>): Webhooks.found (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=found) def found(-A: Data, r: Result<&1, &1, Err, Bool>, v: A) -> Result<&1, &1, Err, A>: Webhooks.back (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=back) # The body back beside a failure. def back(-A: Data, r: Bytes.Bytes & Bytes.Bytes, e: Err) -> IO(Bytes.Bytes & Result<&1, &1, Err, A>): Webhooks.run.mac (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=run.mac) def run.mac(-A: Data, v: A, pre: String, +sigs: List<&2, String>, +std: Bool, +hex: Bool, secrets: List<&2, String>, r: Bytes.Bytes & Bytes.Bytes) -> IO(Bytes.Bytes & Result<&1, &1, Err, A>): Webhooks.run (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=run) # c: the header checks' answer, the signed prefix before the body, and the candidate signatures. def run(-A: Data, c: Result<&1, &1, Err, A & String & List<&2, String>>, +std: Bool, +hex: Bool, secrets: List<&2, String>, r: Bytes.Bytes & Bytes.Bytes) -> IO(Bytes.Bytes & Result<&1, &1, Err, A>): Webhooks.std.sigs (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=std.sigs) # The v1 entries of a space-separated webhook-signature; other versions are skipped. def std.sigs(xs: List<&2, String>) -> List<&2, String>: Webhooks.std.check (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=std.check) def std.check(+tol: U32, now: Time.Instant, +h: Map<&2, List<&2, String>>) -> Result<&1, &1, Err, String & String & List<&2, String>>: Webhooks.verify.with (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=verify.with) # Done with the webhook-id when a v1 signature in webhook-signature signs id.timestamp.body under a secret, # and webhook-timestamp is within tol seconds of now. def verify.with(+tol: U32, secrets: List<&2, String>, now: Time.Instant, +headers: Map<&2, List<&2, String>>, body: Bytes.Bytes) -> IO(Bytes.Bytes & Result<&1, &1, Err, String>): Webhooks.verify (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=verify) # verify.with a 300 s tolerance. def verify(secrets: List<&2, String>, now: Time.Instant, +headers: Map<&2, List<&2, String>>, body: Bytes.Bytes) -> IO(Bytes.Bytes & Result<&1, &1, Err, String>): Webhooks.sign.check (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=sign.check) def sign.check(+id: String, +ts: Int.I64) -> Result<&1, &1, Err, String & String>: Webhooks.sign.headers (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=sign.headers) def sign.headers(+id: String, +ts: String, m: Result<&1, &1, Err, Bytes.Bytes>) -> Result<&1, &1, Err, Map<&2, List<&2, String>>>: Webhooks.sign.mac (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=sign.mac) def sign.mac(k: Bytes.Bytes, +id: String, +ts: String, r: Bytes.Bytes & Bytes.Bytes) -> IO(Bytes.Bytes & Result<&1, &1, Err, Map<&2, List<&2, String>>>): Webhooks.sign.key (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=sign.key) def sign.key(k: Maybe<&1, Bytes.Bytes>, +id: String, +ts: String, r: Bytes.Bytes & Bytes.Bytes) -> IO(Bytes.Bytes & Result<&1, &1, Err, Map<&2, List<&2, String>>>): Webhooks.sign.go (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=sign.go) def sign.go(c: Result<&1, &1, Err, String & String>, +secret: String, r: Bytes.Bytes & Bytes.Bytes) -> IO(Bytes.Bytes & Result<&1, &1, Err, Map<&2, List<&2, String>>>): Webhooks.sign (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=sign) # The webhook-id, webhook-timestamp, and webhook-signature ("v1,") headers for body. # id: not empty, no '.'. ts: unix seconds, not negative. secret: whsec_; send the prefix. def sign(+id: String, +ts: Int.I64, body: Bytes.Bytes, +secret: String) -> IO(Bytes.Bytes & Result<&1, &1, Err, Map<&2, List<&2, String>>>): Webhooks.stripe.t (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=stripe.t) def stripe.t(s: String, r: List<&2, String> & List<&2, String>) -> List<&2, String> & List<&2, String>: Webhooks.stripe.v.push (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=stripe.v.push) def stripe.v.push(s: String, r: List<&2, String> & List<&2, String>) -> List<&2, String> & List<&2, String>: Webhooks.stripe.v (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=stripe.v) def stripe.v(m: Maybe<&2, String>, r: List<&2, String> & List<&2, String>) -> List<&2, String> & List<&2, String>: Webhooks.stripe.item (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=stripe.item) def stripe.item(t: Maybe<&2, String>, v: Maybe<&2, String>, r: List<&2, String> & List<&2, String>) -> List<&2, String> & List<&2, String>: Webhooks.stripe.items (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=stripe.items) # The t= and v1= values of comma-separated items; other schemes (v0) are skipped. def stripe.items(xs: List<&2, String>) -> List<&2, String> & List<&2, String>: Webhooks.stripe.single (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=stripe.single) def stripe.single(ts: List<&2, String>, vs: List<&2, String>) -> Result<&1, &1, Err, String & List<&2, String>>: Webhooks.stripe.one (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=stripe.one) # Exactly one t=: a second one would leave the signed timestamp ambiguous. def stripe.one(r: List<&2, String> & List<&2, String>) -> Result<&1, &1, Err, String & List<&2, String>>: Webhooks.stripe.when (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=stripe.when) def stripe.when(+tol: U32, now: Time.Instant, p: String & List<&2, String>) -> Result<&1, &1, Err, Unit & String & List<&2, String>>: Webhooks.stripe.check (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=stripe.check) def stripe.check(+tol: U32, now: Time.Instant, +h: Map<&2, List<&2, String>>) -> Result<&1, &1, Err, Unit & String & List<&2, String>>: Webhooks.stripe.verify.with (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=stripe.verify.with) # Done when a v1 hex signature in stripe-signature signs t.body under a secret (the whsec_ text itself, as UTF-8), # and t is within tol seconds of now. def stripe.verify.with(+tol: U32, secrets: List<&2, String>, now: Time.Instant, +headers: Map<&2, List<&2, String>>, body: Bytes.Bytes) -> IO(Bytes.Bytes & Result<&1, &1, Err, Unit>): Webhooks.stripe.verify (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=stripe.verify) # stripe.verify.with a 300 s tolerance, Stripe's default. def stripe.verify(secrets: List<&2, String>, now: Time.Instant, +headers: Map<&2, List<&2, String>>, body: Bytes.Bytes) -> IO(Bytes.Bytes & Result<&1, &1, Err, Unit>): Webhooks.github.check (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=github.check) def github.check(+h: Map<&2, List<&2, String>>) -> Result<&1, &1, Err, Unit & String & List<&2, String>>: Webhooks.github.verify (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=github.verify) # Done when x-hub-signature-256 is sha256= of the body under a secret's UTF-8. GitHub signs no timestamp. def github.verify(secrets: List<&2, String>, +headers: Map<&2, List<&2, String>>, body: Bytes.Bytes) -> IO(Bytes.Bytes & Result<&1, &1, Err, Unit>): Webhooks.SendErr (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=SendErr) type SendErr is Data: SendSign{err: Err} SendNet{err: Hairpin.Err} Webhooks.send.result (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=send.result) def send.result(x: Hairpin.Client & Retry.Budget & Result<&1, &1, Hairpin.Err, Http.Res>) -> Hairpin.Client & Retry.Budget & Result<&1, &1, SendErr, Http.Res>: Webhooks.send.again (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=send.again) # A timeout, a refused connect, 408, 429, or any 5xx may clear. def send.again(r: Result<&1, &1, Http.Err, Http.Res>) -> Result<&1, &1, Http.Err, Http.Res> & Maybe<&2, String>: Webhooks.send.judge (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=send.judge) def send.judge(r: Result<&1, &1, Http.Err, Http.Res>) -> Result<&1, &1, Http.Err, Http.Res> & Hairpin.Verdict: Webhooks.send.signed (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=send.signed) # Receivers deduplicate on the event ID, so the POST is safe to repeat. def send.signed(c: Hairpin.Client, b: Retry.Budget, +url: String, r: Bytes.Bytes & Result<&1, &1, Err, Map<&2, List<&2, String>>>) -> IO(Hairpin.Client & Retry.Budget & Result<&1, &1, SendErr, Http.Res>): Webhooks.send.at (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=send.at) def send.at(c: Hairpin.Client, b: Retry.Budget, url: String, id: String, secret: String, body: Bytes.Bytes, now: Time.Instant) -> IO(Hairpin.Client & Retry.Budget & Result<&1, &1, SendErr, Http.Res>): Webhooks.send.in (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=send.in) # One event and one signature per delivery, inside a caller's retry layer. Every attempt takes from b and # reuses this event ID, timestamp, headers, and raw body; the client's retry setting caps this delivery. # The budget left comes back: pass it to the next delivery of the same operation. def send.in(c: Hairpin.Client, b: Retry.Budget, url: String, id: String, secret: String, body: Bytes.Bytes) -> IO(Hairpin.Client & Retry.Budget & Result<&1, &1, SendErr, Http.Res>): Webhooks.send.drop (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=send.drop) def send.drop(x: Hairpin.Client & Retry.Budget & Result<&1, &1, SendErr, Http.Res>) -> Hairpin.Client & Result<&1, &1, SendErr, Http.Res>: Webhooks.send.budget (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=send.budget) def send.budget(url: String, id: String, secret: String, body: Bytes.Bytes, y: Hairpin.Client & Retry.Budget) -> IO(Hairpin.Client & Retry.Budget & Result<&1, &1, SendErr, Http.Res>): Webhooks.send.with (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=send.with) # n extra attempts, on a budget of n + 1 and the client's deadline, with Hairpin's backoff. The client comes back with retry n. def send.with(+n: U32, c: Hairpin.Client, url: String, id: String, secret: String, body: Bytes.Bytes) -> IO(Hairpin.Client & Result<&1, &1, SendErr, Http.Res>): Webhooks.send (https://jend.leeeet.dev/definition.txt?path=bend-kit-webhooks@0.11.0.1/webhooks.bend&name=send) # Three extra attempts by default. def send(c: Hairpin.Client, url: String, id: String, secret: String, body: Bytes.Bytes) -> IO(Hairpin.Client & Result<&1, &1, SendErr, Http.Res>):