@particle-academy/fancy-connector-core 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,80 @@ All notable changes to `fancy-connector-core` are documented here, in
6
6
  **This package is pre-1.0, so breaking changes land in MINOR releases.** The
7
7
  version number is not a promise it can keep yet; the entries below are.
8
8
 
9
+ ## [0.13.0] - 2026-11-01
10
+
11
+ ### Added
12
+
13
+ - **`verifyJwt` / `Jwt::verify`: RS256 JWT verification against keys the
14
+ HOST supplies.** The core never fetches a key set. Every rule fails closed:
15
+ RS256 only, with `none` and `HS256` refused by name; a `kid` must name a
16
+ supplied key; `exp` is required and `nbf` honoured, both with 60 s of
17
+ leeway; the audience is REQUIRED unless the caller passes `null` on
18
+ purpose; the issuer is matched when given. Reasons are fixed strings. Both
19
+ runtimes read `fixtures/jwt/cases.json`, led by RFC 7515 Appendix A.2,
20
+ which verifies from the RFC's own inputs.
21
+ - **The `oidc-jwt` verification scheme, for Google Cloud Pub/Sub push**
22
+ (Gmail's `users.watch` notifications). `verifyOidcDelivery` /
23
+ `OidcDelivery::verify`, reached through `verifyDelivery`'s new optional
24
+ fifth argument, an `OidcExpectation` (`keys`, `audience`, `principal`, all
25
+ the host's). It refuses every push when any of the three is unconfigured,
26
+ reads `Bearer <token>` case-insensitively, verifies the JWT, then requires
27
+ the scheme's `principalClaim` (`email`) to EQUAL the configured service
28
+ account and its `verifiedClaim` (`email_verified`) to be the literal
29
+ `true`. The principal check is what stops a stranger's push subscription,
30
+ aimed at your URL with your URL as its audience, whose token Google signs
31
+ correctly. `fixtures/oidc-delivery/cases.json` has 19 authored rows.
32
+ - **The `pubsub-push` decode kind.** `decodePubSubPush` /
33
+ `PubSubPush::decode`, also through `decodeDelivery` /
34
+ `DeliveryDecode::apply`. It unwraps Pub/Sub's push envelope to
35
+ `{subscription, messageId, publishTime, attributes, deliveryAttempt, data}`.
36
+ `data` may be in either base64 alphabet, padded or not, and is parsed as
37
+ JSON. Malformed input is refused BY NAME: `not-json`, `missing-message`,
38
+ `missing-data`, `bad-encoding` or `data-not-json`. Held to the 13-case
39
+ corpus under `fixtures/pubsub-push/`.
40
+
41
+ ### Changed
42
+
43
+ - `DeliveryDecode` (TS) is now a union,
44
+ `{kind: "form-field-json", field} | {kind: "pubsub-push"}`, and
45
+ `DELIVERY_DECODE_KINDS` / `DeliveryDecode::KINDS` gain `"pubsub-push"`. A
46
+ declaration written as a literal is unaffected. Code that reads `.field` off
47
+ a `DeliveryDecode` it did not construct must narrow on `kind` first.
48
+
49
+ `CONNECTOR_API_VERSION` is unchanged: everything here is optional.
50
+
51
+ ## [0.12.0] - 2026-11-01
52
+
53
+ ### Added
54
+
55
+ - **A signed REQUEST LINE and millisecond timestamps (HubSpot v3).** HubSpot
56
+ signs `base64(HMAC-SHA256(client secret, method + uri + body + timestamp))`,
57
+ sends `X-HubSpot-Request-Timestamp` in MILLISECONDS, and signs the URI with
58
+ only its QUERY portion percent-decoded for twelve escapes (never the leading
59
+ `?`, any `#fragment` dropped). The pieces:
60
+ - `InboundDelivery` gains optional `method` and `url`; pass the request
61
+ line exactly as it arrived.
62
+ - `HmacScheme` gains `timestampUnit` (`"s"` | `"ms"`), `signsRequestLine`
63
+ (a delivery without its method or URL is refused by name: `delivery
64
+ carried no request method or url`), and `uri: "hubspot-v3"`.
65
+ - The CORE normalises the URI (`normaliseSignedUri` /
66
+ `WebhookVerifier::normaliseSignedUri`; the rules ship as data, in
67
+ `SIGNED_URI_RULES`), and a scheme's `payload` receives the request line
68
+ as a fourth argument.
69
+ - PHP's new `verify()` parameters are appended, so existing calls are
70
+ unchanged.
71
+
72
+ The signed-delivery corpus gains four HubSpot rows, led by HubSpot's
73
+ PUBLISHED worked example, which reproduces from its inputs.
74
+ - **`TriggerDescriptor.route` `{by, path}`.** It names the one key a delivery
75
+ that reaches ONE endpoint for many tenants may be routed by (HubSpot's
76
+ `portalId`; Gmail's `emailAddress`). The rule is fixed: route only after
77
+ verification, only to a connection or watch the host minted, and drop an
78
+ unmapped key with a 2xx and a log line, creating nothing. The package
79
+ declares; the host routes.
80
+
81
+ `CONNECTOR_API_VERSION` is unchanged: everything here is optional.
82
+
9
83
  ## [0.11.0] - 2026-10-28
10
84
 
11
85
  ### Added