@vellumai/vellum-gateway 0.4.30 → 0.4.31

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/vellum-gateway",
3
- "version": "0.4.30",
3
+ "version": "0.4.31",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./twilio/verify": "./src/twilio/verify.ts",
@@ -9,9 +9,9 @@ describe("matchContactsControlPlaneRoute", () => {
9
9
  expect(matchContactsControlPlaneRoute("/v1/contacts", "POST")).toEqual({
10
10
  kind: "upsertContact",
11
11
  });
12
- expect(matchContactsControlPlaneRoute("/v1/contacts/merge", "POST")).toEqual(
13
- { kind: "mergeContacts" },
14
- );
12
+ expect(
13
+ matchContactsControlPlaneRoute("/v1/contacts/merge", "POST"),
14
+ ).toEqual({ kind: "mergeContacts" });
15
15
  expect(
16
16
  matchContactsControlPlaneRoute("/v1/contacts/channels/ch_1", "PATCH"),
17
17
  ).toEqual({ kind: "updateContactChannel", channelId: "ch_1" });
@@ -21,6 +21,27 @@ describe("matchContactsControlPlaneRoute", () => {
21
21
  });
22
22
  });
23
23
 
24
+ test("matches verify contact channel route", () => {
25
+ expect(
26
+ matchContactsControlPlaneRoute(
27
+ "/v1/contacts/ct_1/channels/ch_1/verify",
28
+ "POST",
29
+ ),
30
+ ).toEqual({
31
+ kind: "verifyContactChannel",
32
+ contactId: "ct_1",
33
+ channelId: "ch_1",
34
+ });
35
+
36
+ // Only POST is supported
37
+ expect(
38
+ matchContactsControlPlaneRoute(
39
+ "/v1/contacts/ct_1/channels/ch_1/verify",
40
+ "GET",
41
+ ),
42
+ ).toBeNull();
43
+ });
44
+
24
45
  test("returns null for unsupported methods on contact routes", () => {
25
46
  expect(matchContactsControlPlaneRoute("/v1/contacts", "DELETE")).toBeNull();
26
47
  // GET /v1/contacts/channels/ch_1 does not match (PATCH only)
@@ -31,10 +52,12 @@ describe("matchContactsControlPlaneRoute", () => {
31
52
 
32
53
  test("GET /v1/contacts/merge falls through to getContact", () => {
33
54
  // No GET handler for /merge, so the contactId catch-all picks it up
34
- expect(matchContactsControlPlaneRoute("/v1/contacts/merge", "GET")).toEqual({
35
- kind: "getContact",
36
- contactId: "merge",
37
- });
55
+ expect(matchContactsControlPlaneRoute("/v1/contacts/merge", "GET")).toEqual(
56
+ {
57
+ kind: "getContact",
58
+ contactId: "merge",
59
+ },
60
+ );
38
61
  });
39
62
 
40
63
  test("matches redeem invite only for POST", () => {
@@ -121,6 +121,18 @@ export function createContactsControlPlaneProxyHandler(config: GatewayConfig) {
121
121
  return proxyToRuntime(req, `/v1/contacts/channels/${channelId}`, "");
122
122
  },
123
123
 
124
+ async handleVerifyContactChannel(
125
+ req: Request,
126
+ contactId: string,
127
+ channelId: string,
128
+ ): Promise<Response> {
129
+ return proxyToRuntime(
130
+ req,
131
+ `/v1/contacts/${contactId}/channels/${channelId}/verify`,
132
+ "",
133
+ );
134
+ },
135
+
124
136
  // ── Invite routes ──
125
137
  async handleListInvites(req: Request): Promise<Response> {
126
138
  const url = new URL(req.url);
@@ -7,7 +7,8 @@ export type ContactsControlPlaneRoute =
7
7
  | { kind: "listInvites" }
8
8
  | { kind: "createInvite" }
9
9
  | { kind: "redeemInvite" }
10
- | { kind: "revokeInvite"; inviteId: string };
10
+ | { kind: "revokeInvite"; inviteId: string }
11
+ | { kind: "verifyContactChannel"; contactId: string; channelId: string };
11
12
 
12
13
  export function matchContactsControlPlaneRoute(
13
14
  pathname: string,
@@ -30,6 +31,18 @@ export function matchContactsControlPlaneRoute(
30
31
  return { kind: "updateContactChannel", channelId: channelMatch[1] };
31
32
  }
32
33
 
34
+ // Trusted channel verification
35
+ const verifyMatch = pathname.match(
36
+ /^\/v1\/contacts\/([^/]+)\/channels\/([^/]+)\/verify$/,
37
+ );
38
+ if (verifyMatch && method === "POST") {
39
+ return {
40
+ kind: "verifyContactChannel",
41
+ contactId: verifyMatch[1],
42
+ channelId: verifyMatch[2],
43
+ };
44
+ }
45
+
33
46
  // ── Invite routes ──
34
47
  if (pathname === "/v1/contacts/invites") {
35
48
  if (method === "GET") return { kind: "listInvites" };
package/src/index.ts CHANGED
@@ -373,6 +373,17 @@ function main() {
373
373
  handler: (req, params) =>
374
374
  contactsControlPlaneProxy.handleUpdateContactChannel(req, params[0]),
375
375
  },
376
+ {
377
+ path: /^\/v1\/contacts\/([^/]+)\/channels\/([^/]+)\/verify$/,
378
+ method: "POST",
379
+ auth: "edge",
380
+ handler: (req, params) =>
381
+ contactsControlPlaneProxy.handleVerifyContactChannel(
382
+ req,
383
+ params[0],
384
+ params[1],
385
+ ),
386
+ },
376
387
 
377
388
  // ── Contacts/invites control plane ──
378
389
  {