@conveo/conveo-sdk 0.3.0 → 0.4.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/README.md CHANGED
@@ -57,6 +57,26 @@ user.email; // "you@conveo.ai"
57
57
  const res = await gatewayFetch("/postgrest/Organization?select=id,name", { user });
58
58
  ```
59
59
 
60
+ `gatewayFetch` can also call as the **app itself** instead of a user — for
61
+ gateway-fronted vendor APIs whose key lives at the gateway (HubSpot, Linear, …).
62
+ You authenticate with the app's Vercel OIDC identity; the gateway checks a Grant
63
+ and injects the vendor key on the upstream leg, so your app never holds it:
64
+
65
+ ```ts
66
+ // `service` targets the vendor API's own host; `identity: "app"` uses the
67
+ // app's VERCEL_OIDC_TOKEN as the bearer (the default when there's no `user`).
68
+ const res = await gatewayFetch("/crm/v3/objects/contacts?limit=3", {
69
+ identity: "app",
70
+ service: "hubspot",
71
+ });
72
+ ```
73
+
74
+ `service` resolves to `AGENTGATEWAY_SERVICE_<NAME>_URL` if set, else
75
+ `https://<name>.internal.conveo.ai` (override the suffix with
76
+ `AGENTGATEWAY_SERVICE_DOMAIN`). Install `@vercel/functions` for automatic
77
+ refresh of the short-lived OIDC token; without it the SDK reads
78
+ `VERCEL_OIDC_TOKEN` directly.
79
+
60
80
  The `user` you get back looks like this:
61
81
 
62
82
  ```ts
@@ -138,6 +158,8 @@ conveo-realm user tokens carry no `aud` claim today.
138
158
  | `AGENTGATEWAY_SIGNIN_URL` | — | Browser 302 target; unset → always 401 |
139
159
  | `AGENTGATEWAY_AUTH_MODE` | `required` | `optional` verifies but never rejects |
140
160
  | `AGENTGATEWAY_API_URL` / `_MCP_URL` | gateway prod hosts | `gatewayFetch` bases |
161
+ | `AGENTGATEWAY_SERVICE_<NAME>_URL` | `https://<name>.<domain>` | Override a `gatewayFetch({ service })` host (e.g. `AGENTGATEWAY_SERVICE_HUBSPOT_URL`) |
162
+ | `AGENTGATEWAY_SERVICE_DOMAIN` | `internal.conveo.ai` | Suffix for unresolved `service` hosts |
141
163
  | `AGENTGATEWAY_DEV_TOKEN` / `_DEV_MOCK_USER` | — | Local dev only; honored only when `NODE_ENV` or `VERCEL_ENV` is `development` |
142
164
 
143
165
  Code options: `createGatewayProxy({ publicPaths: ["/api/health"], ... })` —
package/dist/server.d.ts CHANGED
@@ -19,12 +19,33 @@ export interface GatewayFetchOptions extends RequestInit {
19
19
  identity?: "user" | "app";
20
20
  /** Which gateway host to target. Default `api` (gateway.ops); `mcp` for MCP/LLM routes. */
21
21
  base?: keyof typeof DEFAULT_BASES;
22
+ /**
23
+ * A host-based, gateway-fronted vendor API to target instead of `base` —
24
+ * e.g. `"hubspot"` or `"linear"`. These live on their own hostname (the
25
+ * gateway rewrites the Host to the real vendor and injects the vendor key
26
+ * server-side), not on a path under gateway.ops, so they can't be reached
27
+ * with `base`. Resolves to `AGENTGATEWAY_SERVICE_<NAME>_URL` if set, else
28
+ * `https://<name>.<AGENTGATEWAY_SERVICE_DOMAIN ?? internal.conveo.ai>`.
29
+ *
30
+ * Such calls are authorized as the **app** (the gateway Grant is on the
31
+ * Vercel deployment), so they default to `identity: "app"`. Mutually
32
+ * exclusive with `base`.
33
+ */
34
+ service?: string;
22
35
  }
23
36
  /**
24
37
  * Fetch a gateway route with the right credential:
25
38
  *
26
39
  * ```ts
27
- * const res = await gatewayFetch("/postgrest/Organization?select=id,name&limit=3", { user });
40
+ * // on behalf of the signed-in user (their forwarded token):
41
+ * await gatewayFetch("/postgrest/Organization?select=id,name&limit=3", { user });
42
+ *
43
+ * // as the app itself, against a gateway-fronted vendor API (HubSpot): the
44
+ * // gateway injects HubSpot's key server-side — the app never holds it.
45
+ * await gatewayFetch("/crm/v3/objects/contacts?limit=3", {
46
+ * identity: "app",
47
+ * service: "hubspot",
48
+ * });
28
49
  * ```
29
50
  */
30
51
  export declare function gatewayFetch(path: string, options?: GatewayFetchOptions): Promise<Response>;
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- import{headers as E}from"next/headers";import{configFromEnv as d,isDevelopment as f}from"./adapters/env.js";import{GatewayAuthError as h,IDENTITY_HEADERS as m}from"./core/types.js";import{createVerifier as l}from"./core/verify.js";let w;function v(){return w??=l(d(process.env)),w}async function k(){const e=(await E()).get(m.token);if(!e){const t=process.env.AGENTGATEWAY_DEV_MOCK_USER;if(t&&f(process.env)){const r=t.toLowerCase();return{sub:"dev-mock-user",email:r,emailVerified:!0,token:"",claims:{sub:"dev-mock-user",email:r}}}throw new h("unauthenticated","no gateway user on this request \u2014 public path, optional auth, or middleware not applied")}return v().verifyToken(e)}const y={api:"https://gateway.ops.conveo.ai",mcp:"https://mcp.ops.conveo.ai"};async function G(s,e={}){const{user:t,identity:r=e.user?"user":"app",base:c="api",...u}=e,n=process.env,o=(c==="mcp"?n.AGENTGATEWAY_MCP_URL:n.AGENTGATEWAY_API_URL)??y[c],a=new URL(s,o.endsWith("/")?o:`${o}/`);if(a.origin!==new URL(o).origin)throw new Error(`gatewayFetch path must stay on the gateway origin (resolved to ${a.origin})`);const i=new Headers(u.headers);if(r==="user"){if(!t?.token)throw new h("unauthenticated",'gatewayFetch with identity "user" needs a verified user with a token (mock users have none)');i.set("authorization",`Bearer ${t.token}`)}else{const p=n.VERCEL_OIDC_TOKEN;if(!p)throw new Error("VERCEL_OIDC_TOKEN is not available \u2014 enable OIDC federation on the Vercel project (or `vercel env pull` for local dev)");i.set("authorization",`Bearer ${p}`)}return fetch(a,{...u,headers:i})}import{GatewayAuthError as L}from"./core/types.js";export{L as GatewayAuthError,G as gatewayFetch,k as getGatewayUser};
1
+ import{headers as f}from"next/headers";import{configFromEnv as d,isDevelopment as w}from"./adapters/env.js";import{GatewayAuthError as l,IDENTITY_HEADERS as m}from"./core/types.js";import{createVerifier as v}from"./core/verify.js";let E;function A(){return E??=v(d(process.env)),E}async function V(){const e=(await f()).get(m.token);if(!e){const t=process.env.AGENTGATEWAY_DEV_MOCK_USER;if(t&&w(process.env)){const o=t.toLowerCase();return{sub:"dev-mock-user",email:o,emailVerified:!0,token:"",claims:{sub:"dev-mock-user",email:o}}}throw new l("unauthenticated","no gateway user on this request \u2014 public path, optional auth, or middleware not applied")}return A().verifyToken(e)}const g={api:"https://gateway.ops.conveo.ai",mcp:"https://mcp.ops.conveo.ai"},_=/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;function y(r,e){if(!_.test(r))throw new Error(`gatewayFetch: invalid service name "${r}" \u2014 expected a lowercase DNS label (letters, digits, dashes)`);const t=e[`AGENTGATEWAY_SERVICE_${r.toUpperCase().replace(/-/g,"_")}_URL`];if(t)return t;const o=e.AGENTGATEWAY_SERVICE_DOMAIN??"internal.conveo.ai";return`https://${r}.${o}`}async function T(r){try{const{getVercelOidcToken:t}=await import("@vercel/functions/oidc"),o=await t();if(o)return o}catch{}const e=r.VERCEL_OIDC_TOKEN;if(!e)throw new Error("VERCEL_OIDC_TOKEN is not available \u2014 enable OIDC federation on the Vercel project (or `vercel env pull` for local dev). Install @vercel/functions for automatic token refresh.");return e}async function I(r,e={}){const{user:t,identity:o=e.user?"user":"app",base:c,service:u,...h}=e,a=process.env;let n;if(u!==void 0){if(c!==void 0)throw new Error("gatewayFetch: pass either `service` or `base`, not both");n=y(u,a)}else{const p=c??"api";n=(p==="mcp"?a.AGENTGATEWAY_MCP_URL:a.AGENTGATEWAY_API_URL)??g[p]}const i=new URL(r,n.endsWith("/")?n:`${n}/`);if(i.origin!==new URL(n).origin)throw new Error(`gatewayFetch path must stay on the gateway origin (resolved to ${i.origin})`);const s=new Headers(h.headers);if(o==="user"){if(!t?.token)throw new l("unauthenticated",'gatewayFetch with identity "user" needs a verified user with a token (mock users have none)');s.set("authorization",`Bearer ${t.token}`)}else s.set("authorization",`Bearer ${await T(a)}`);return fetch(i,{...h,headers:s})}import{GatewayAuthError as b}from"./core/types.js";export{b as GatewayAuthError,I as gatewayFetch,V as getGatewayUser};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conveo/conveo-sdk",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "SDK for Conveo apps behind the agent gateway: drop-in auth middleware (Next.js / Vercel / Supabase), server helpers, and a dev-token CLI.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -42,7 +42,7 @@
42
42
  }
43
43
  },
44
44
  "bin": {
45
- "agentgateway-dev-token": "./dist/dev/token.js"
45
+ "agentgateway-dev-token": "dist/dev/token.js"
46
46
  },
47
47
  "scripts": {
48
48
  "build": "tsc -p tsconfig.build.json && pnpm minify && pnpm build:deno",