@substrat-run/vertical-host 0.163.0 → 0.164.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.
@@ -0,0 +1,49 @@
1
+ import type { MailInAddress, MailInRelayRequest } from '@substrat-run/contracts';
2
+ /**
3
+ * This scope's inbound mail address, from a VERTICAL's worker (#2611).
4
+ *
5
+ * A scope that declares a mail-in landing can have an address on the platform's receiving
6
+ * subdomain — mail sent to it lands through the declared operation, attachment bytes included.
7
+ * This is how the vertical asks for one, reads it to show its users, rotates it when it leaks, and
8
+ * gives it up. The same shape as {@link requestConnectUrl}: the operation decides, the harness
9
+ * effects.
10
+ *
11
+ * ```ts
12
+ * // module.ts — the authorizing act
13
+ * const manageMailIn: OperationHandler = async (ctx) => {
14
+ * assertAllowed(await ctx.check(PERM.manageMailIn));
15
+ * return { principal: ctx.principal };
16
+ * };
17
+ *
18
+ * // worker.ts — the effect
19
+ * const { principal } = await scope.invoke('docs/manage-mail-in', {});
20
+ * const address = await mailInAddress({
21
+ * controlPlaneUrl: env.CONTROL_PLANE_URL,
22
+ * platformSecret: env.PLATFORM_SECRET,
23
+ * tenantId, scopeId,
24
+ * action: 'request',
25
+ * createdBy: principal,
26
+ * allowlist: ['me@example.com'],
27
+ * });
28
+ * ```
29
+ *
30
+ * Call it from the worker, never from inside a Durable Object: the platform requires a PROVEN
31
+ * caller for every action, since an address delivers into the scope it names. Which operation and
32
+ * key the address lands through is read from the manifest the scope runs, never from this call.
33
+ */
34
+ export type MailInAddressRequest = MailInRelayRequest & {
35
+ /** The control plane's origin, injected into the vertical as `CONTROL_PLANE_URL`. */
36
+ controlPlaneUrl: string;
37
+ /** The `PLATFORM_SECRET` injected into this dispatch script. */
38
+ platformSecret: string;
39
+ /** `fetch` seam for tests; defaults to the runtime's, bound (see `lint:bound-fetch`). */
40
+ fetchImpl?: typeof fetch;
41
+ };
42
+ /** The relay refused, or could not be reached. Carries the status so a caller can map it. */
43
+ export declare class MailInAddressError extends Error {
44
+ readonly status: number;
45
+ constructor(message: string, status: number);
46
+ }
47
+ /** The scope's address after the action — `null` when it has none (or just gave it up). */
48
+ export declare function mailInAddress(request: MailInAddressRequest): Promise<MailInAddress | null>;
49
+ //# sourceMappingURL=mail-in.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mail-in.d.ts","sourceRoot":"","sources":["../src/mail-in.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,GAAG;IACtD,qFAAqF;IACrF,eAAe,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,CAAC;AAEF,6FAA6F;AAC7F,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,MAAM,EAAE,MAAM;IAFzB,YACE,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM,EAIxB;CACF;AAED,2FAA2F;AAC3F,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAmBhG"}
@@ -0,0 +1,32 @@
1
+ import { PLATFORM_SECRET_HEADER, mailInRelayResult } from '@substrat-run/contracts';
2
+ /** The relay refused, or could not be reached. Carries the status so a caller can map it. */
3
+ export class MailInAddressError extends Error {
4
+ status;
5
+ constructor(message, status) {
6
+ super(message);
7
+ this.status = status;
8
+ this.name = 'MailInAddressError';
9
+ }
10
+ }
11
+ /** The scope's address after the action — `null` when it has none (or just gave it up). */
12
+ export async function mailInAddress(request) {
13
+ const fetchImpl = request.fetchImpl ?? globalThis.fetch.bind(globalThis);
14
+ const base = request.controlPlaneUrl.replace(/\/+$/, '');
15
+ const res = await fetchImpl(`${base}/internal/mail-in/address`, {
16
+ method: 'POST',
17
+ headers: { 'content-type': 'application/json', [PLATFORM_SECRET_HEADER]: request.platformSecret },
18
+ body: JSON.stringify({
19
+ tenantId: request.tenantId,
20
+ scopeId: request.scopeId,
21
+ action: request.action,
22
+ ...(request.createdBy ? { createdBy: request.createdBy } : {}),
23
+ ...(request.allowlist ? { allowlist: request.allowlist } : {}),
24
+ }),
25
+ });
26
+ const body = (await res.json().catch(() => ({})));
27
+ if (!res.ok) {
28
+ throw new MailInAddressError(`the platform refused the mail-in ${request.action} (${res.status}): ${body.error ?? 'unknown error'}`, res.status);
29
+ }
30
+ return mailInRelayResult.parse(body).address;
31
+ }
32
+ //# sourceMappingURL=mail-in.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mail-in.js","sourceRoot":"","sources":["../src/mail-in.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AA4CpF,6FAA6F;AAC7F,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAGhC,MAAM;IAFjB,YACE,OAAe,EACN,MAAc;QAEvB,KAAK,CAAC,OAAO,CAAC,CAAC;sBAFN,MAAM;QAGf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,2FAA2F;AAC3F,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA6B;IAC/D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,2BAA2B,EAAE;QAC9D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC,cAAc,EAAE;QACjG,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/D,CAAC;KACH,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAuB,CAAC;IACxE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,kBAAkB,CAAC,oCAAoC,OAAO,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,MAAM,IAAI,CAAC,KAAK,IAAI,eAAe,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnJ,CAAC;IACD,OAAO,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;AAC/C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@substrat-run/vertical-host",
3
- "version": "0.163.0",
3
+ "version": "0.164.0",
4
4
  "description": "The platform's /internal/* surface + error envelope, authored once — mount it in a vertical worker instead of re-copying the control-plane contract",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -20,28 +20,32 @@
20
20
  "./model": {
21
21
  "types": "./dist/model.d.ts",
22
22
  "default": "./dist/model.js"
23
+ },
24
+ "./connectors": {
25
+ "types": "./dist/connectors.d.ts",
26
+ "default": "./dist/connectors.js"
23
27
  }
24
28
  },
25
29
  "files": [
26
30
  "dist"
27
31
  ],
28
32
  "dependencies": {
29
- "ai": "7.0.142",
33
+ "ai": "7.0.152",
30
34
  "hono": "^4.13.13",
31
35
  "workers-ai-provider": "^4.0.0",
32
- "@substrat-run/contracts": "^0.163.0",
33
- "@substrat-run/model-providers": "^0.5.53",
34
- "@substrat-run/kernel": "^0.163.0"
36
+ "@substrat-run/contracts": "^0.164.0",
37
+ "@substrat-run/model-providers": "^0.5.54",
38
+ "@substrat-run/kernel": "^0.164.0"
35
39
  },
36
40
  "devDependencies": {
37
- "@scalar/api-reference": "1.75.0",
41
+ "@scalar/api-reference": "1.76.0",
38
42
  "@types/better-sqlite3": "^9.6.0",
39
43
  "better-sqlite3": "^13.0.3",
40
44
  "typescript": "^7.0.0",
41
45
  "vitest": "^5.0.5",
42
- "@substrat-run/vertical-auth": "^0.28.3",
43
- "@substrat-run/adapter-sqlite": "^0.163.0",
44
- "@substrat-run/contract-tests": "^0.163.0"
46
+ "@substrat-run/adapter-sqlite": "^0.164.0",
47
+ "@substrat-run/contract-tests": "^0.164.0",
48
+ "@substrat-run/vertical-auth": "^0.28.4"
45
49
  },
46
50
  "publishConfig": {
47
51
  "access": "public"