@celsoft/platform 0.10.0 → 0.12.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.
Files changed (44) hide show
  1. package/dist/adapters/process.js +8 -6
  2. package/dist/adapters/process.js.map +1 -1
  3. package/dist/cli.js +11 -1
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +1 -0
  6. package/dist/config.js +3 -1
  7. package/dist/config.js.map +1 -1
  8. package/dist/generate.d.ts +3 -0
  9. package/dist/generate.js +60 -0
  10. package/dist/generate.js.map +1 -0
  11. package/dist/runtime/auth.d.ts +2782 -0
  12. package/dist/runtime/auth.js +19 -3
  13. package/dist/runtime/auth.js.map +1 -1
  14. package/dist/runtime/client.d.ts +20 -0
  15. package/dist/runtime/client.js +28 -0
  16. package/dist/runtime/client.js.map +1 -0
  17. package/dist/runtime/endpoint-error.d.ts +4 -0
  18. package/dist/runtime/endpoint-error.js +11 -0
  19. package/dist/runtime/endpoint-error.js.map +1 -0
  20. package/dist/runtime/endpoints.d.ts +30 -0
  21. package/dist/runtime/endpoints.js +89 -0
  22. package/dist/runtime/endpoints.js.map +1 -0
  23. package/dist/runtime/guard.js +5 -0
  24. package/dist/runtime/guard.js.map +1 -1
  25. package/dist/runtime/index.d.ts +14 -3
  26. package/dist/runtime/index.js +67 -7
  27. package/dist/runtime/index.js.map +1 -1
  28. package/dist/runtime/live.d.ts +10 -2
  29. package/dist/runtime/live.js +11 -3
  30. package/dist/runtime/live.js.map +1 -1
  31. package/dist/runtime/mcp.d.ts +11 -0
  32. package/dist/runtime/mcp.js +61 -0
  33. package/dist/runtime/mcp.js.map +1 -0
  34. package/dist/runtime/screens.d.ts +1 -1
  35. package/dist/runtime/screens.js +45 -5
  36. package/dist/runtime/screens.js.map +1 -1
  37. package/dist/schema.d.ts +5119 -485
  38. package/dist/schema.js +171 -2
  39. package/dist/schema.js.map +1 -1
  40. package/dist/wrangler-config.d.ts +1 -1
  41. package/dist/wrangler-config.js +7 -6
  42. package/dist/wrangler-config.js.map +1 -1
  43. package/package.json +15 -4
  44. package/schema.json +5 -0
@@ -1,6 +1,7 @@
1
1
  import { betterAuth } from "better-auth";
2
2
  import { drizzleAdapter } from "better-auth/adapters/drizzle";
3
- import { admin, organization } from "better-auth/plugins";
3
+ import { mcp } from "@better-auth/mcp";
4
+ import { admin, jwt, organization } from "better-auth/plugins";
4
5
  import { adminAc, userAc } from "better-auth/plugins/admin/access";
5
6
  import { sql } from "drizzle-orm";
6
7
  import { authSchema } from "../schema.js";
@@ -12,6 +13,8 @@ export function createAuth({ db, secret, baseURL, email, requireVerification })
12
13
  baseURL,
13
14
  basePath: AUTH_PATH,
14
15
  database: drizzleAdapter(db, { provider: "pg", schema: authSchema }),
16
+ // The JWT plugin's session-to-token route is not part of the platform.
17
+ disabledPaths: ["/token"],
15
18
  // Postgres fills every id with uuidv7(), so Better Auth leaves the column out.
16
19
  advanced: { database: { generateId: "uuid" } },
17
20
  // The Workers rate limiting binding guards these routes before Better Auth sees them.
@@ -45,8 +48,8 @@ export function createAuth({ db, secret, baseURL, email, requireVerification })
45
48
  },
46
49
  },
47
50
  },
48
- // Always installed so its tables and types never change; the runtime hides its routes
49
- // unless platform.jsonc turns organizations on.
51
+ // Always installed so their tables and types never change; the runtime hides their routes
52
+ // unless platform.jsonc turns organizations or MCP on.
50
53
  plugins: [
51
54
  admin({ defaultRole: "user", adminRoles: [OWNER_ROLE, "admin"], roles: { [OWNER_ROLE]: adminAc, admin: adminAc, user: userAc } }),
52
55
  organization({
@@ -59,6 +62,19 @@ export function createAuth({ db, secret, baseURL, email, requireVerification })
59
62
  });
60
63
  },
61
64
  }),
65
+ // The OAuth server AI clients sign in through to reach the app's MCP endpoints; its tokens
66
+ // are JWTs bound to the app's /mcp, signed with keys the JWT plugin keeps.
67
+ jwt(),
68
+ mcp({
69
+ loginPage: "/login",
70
+ consentPage: "/consent",
71
+ resource: `${baseURL}/mcp`,
72
+ scopes: ["openid", "profile", "email", "offline_access"],
73
+ allowDynamicClientRegistration: true,
74
+ allowUnauthenticatedClientRegistration: true,
75
+ // Clients that leave out their type are judged by their redirect URIs, so local ones work.
76
+ clientRegistrationDefaultApplicationType: "infer",
77
+ }),
62
78
  ],
63
79
  });
64
80
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/runtime/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;AACrC,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC;AAUlC,MAAM,UAAU,UAAU,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAgB;IAC1F,OAAO,UAAU,CAAC;QAChB,MAAM;QACN,OAAO;QACP,QAAQ,EAAE,SAAS;QACnB,QAAQ,EAAE,cAAc,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QACpE,+EAA+E;QAC/E,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE;QAC9C,sFAAsF;QACtF,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;QAC7B,OAAO,EAAE;YACP,yFAAyF;YACzF,2DAA2D;YAC3D,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;SAC/C;QACD,gBAAgB,EAAE;YAChB,OAAO,EAAE,IAAI;YACb,wBAAwB,EAAE,mBAAmB;YAC7C,iBAAiB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE;gBACzC,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,qBAAqB,EAAE,IAAI,EAAE,2BAA2B,GAAG,qDAAqD,EAAE,CAAC,CAAC;YAClK,CAAC;SACF;QACD,iBAAiB,EAAE;YACjB,YAAY,EAAE,IAAI;YAClB,2BAA2B,EAAE,IAAI;YACjC,qBAAqB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE;gBAC7C,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,kCAAkC,GAAG,EAAE,EAAE,CAAC,CAAC;YACrH,CAAC;SACF;QACD,aAAa,EAAE;YACb,IAAI,EAAE;gBACJ,MAAM,EAAE;oBACN,2FAA2F;oBAC3F,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;wBACpB,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA,4BAA4B,UAAU,eAAe,IAAI,CAAC,EAAE,sDAAsD,UAAU,GAAG,CAAC,CAAC;oBACvJ,CAAC;iBACF;aACF;SACF;QACD,sFAAsF;QACtF,gDAAgD;QAChD,OAAO,EAAE;YACP,KAAK,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;YACjI,YAAY,CAAC;gBACX,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;gBACxB,mBAAmB,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE;oBAC3E,MAAM,KAAK,CAAC,IAAI,CAAC;wBACf,EAAE;wBACF,OAAO,EAAE,QAAQ,GAAG,CAAC,IAAI,EAAE;wBAC3B,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,wBAAwB,GAAG,CAAC,IAAI,QAAQ,OAAO,qBAAqB,EAAE,EAAE;qBACnG,CAAC,CAAC;gBACL,CAAC;aACF,CAAC;SACH;KACF,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/runtime/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { z } from "zod";
2
+ import { EndpointError } from "./endpoint-error.js";
3
+ export { EndpointError };
4
+ type Method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
5
+ type Jsonified<T> = T extends Date ? string : T extends readonly (infer U)[] ? Jsonified<U>[] : T extends object ? {
6
+ [K in keyof T]: Jsonified<T[K]>;
7
+ } : T;
8
+ type EndpointsOf<App> = App extends {
9
+ endpoints: infer E;
10
+ } ? E : never;
11
+ type InputOf<E> = E extends {
12
+ input: infer I extends z.ZodType;
13
+ } ? z.input<I> : never;
14
+ type OutputOf<E> = E extends {
15
+ output: infer O extends z.ZodType;
16
+ } ? Jsonified<z.output<O>> : never;
17
+ export type Call<App> = <Name extends keyof EndpointsOf<App> & string>(name: Name, input: InputOf<EndpointsOf<App>[Name]>) => Promise<OutputOf<EndpointsOf<App>[Name]>>;
18
+ export declare function createCall<App>(routes: Record<string, readonly [Method, string]>, options?: {
19
+ url?: string;
20
+ }): Call<App>;
@@ -0,0 +1,28 @@
1
+ import { createORPCClient, ORPCError } from "@orpc/client";
2
+ import { oc } from "@orpc/contract";
3
+ import { OpenAPILink } from "@orpc/openapi-client/fetch";
4
+ import { EndpointError } from "./endpoint-error.js";
5
+ export { EndpointError };
6
+ // Calls the app's endpoints by name over its REST API; the generated .platform/client.ts passes
7
+ // each endpoint's method and path, and the app's own type for the inputs and outputs.
8
+ export function createCall(routes, options = {}) {
9
+ const contract = Object.fromEntries(Object.entries(routes).map(([name, [method, path]]) => [name, oc.route({ method, path: path })]));
10
+ const url = options.url ?? (typeof location === "undefined" ? undefined : location.origin);
11
+ if (!url)
12
+ throw new Error("createCall needs a url outside a browser");
13
+ const client = createORPCClient(new OpenAPILink(contract, { url }));
14
+ return (async (name, input) => {
15
+ const fn = routes[name] && client[name];
16
+ if (!fn)
17
+ throw new Error(`no API endpoint named ${name}`);
18
+ try {
19
+ return await fn(input);
20
+ }
21
+ catch (error) {
22
+ if (error instanceof ORPCError)
23
+ throw new EndpointError(error.status, error.message);
24
+ throw error;
25
+ }
26
+ });
27
+ }
28
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/runtime/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,CAAC;AAezB,gGAAgG;AAChG,sFAAsF;AACtF,MAAM,UAAU,UAAU,CAAM,MAAiD,EAAE,OAAO,GAAqB,EAAE;IAC/G,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACtJ,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3F,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,gBAAgB,CAAuD,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAE1H,OAAO,CAAC,KAAK,EAAE,IAAY,EAAE,KAAc,EAAE,EAAE;QAC7C,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,SAAS;gBAAE,MAAM,IAAI,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YACrF,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAc,CAAC;AAClB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare class EndpointError extends Error {
2
+ readonly status: number;
3
+ constructor(status: number, message: string);
4
+ }
@@ -0,0 +1,11 @@
1
+ // How an endpoint fails: over the API it is this status with `{ error }`, over MCP a tool error
2
+ // with the message. Shared by the Worker and the browser client, so it imports nothing.
3
+ export class EndpointError extends Error {
4
+ status;
5
+ constructor(status, message) {
6
+ super(message);
7
+ this.status = status;
8
+ this.name = "EndpointError";
9
+ }
10
+ }
11
+ //# sourceMappingURL=endpoint-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint-error.js","sourceRoot":"","sources":["../../src/runtime/endpoint-error.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,wFAAwF;AACxF,MAAM,OAAO,aAAc,SAAQ,KAAK;IAE3B,MAAM;IADjB,YACW,MAAc,EACvB,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;sBAHN,MAAM;QAIf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF"}
@@ -0,0 +1,30 @@
1
+ import type { z } from "zod";
2
+ import type { AppContext } from "./index.js";
3
+ export type AnyApp = AppContext<any, any>;
4
+ export type Method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
5
+ export type Door = "api" | "mcp";
6
+ export interface EndpointDefinition<Input extends z.ZodType, Output extends z.ZodType> {
7
+ serve?: readonly Door[];
8
+ method?: Method;
9
+ path?: string;
10
+ description?: string;
11
+ input: Input;
12
+ output: Output;
13
+ }
14
+ export interface Endpoint<Input extends z.ZodType = z.ZodType, Output extends z.ZodType = z.ZodType, App = AnyApp> extends EndpointDefinition<Input, Output> {
15
+ handler: (input: z.output<Input>, app: App) => z.input<Output> | Promise<z.input<Output>>;
16
+ }
17
+ export declare function endpoint<Input extends z.ZodType, Output extends z.ZodType, App = AnyApp>(definition: EndpointDefinition<Input, Output>, handler: (input: z.output<Input>, app: App) => z.input<Output> | Promise<z.input<Output>>): Endpoint<Input, Output, App>;
18
+ export type Endpoints = Record<string, Endpoint<z.ZodType, z.ZodType, never>>;
19
+ export interface Route {
20
+ method: Method;
21
+ path: string;
22
+ }
23
+ export declare const servesApi: (e: {
24
+ serve?: readonly Door[];
25
+ }) => boolean;
26
+ export declare function apiRoutes(endpoints: Record<string, Omit<Endpoint, "handler">>): Record<string, Route>;
27
+ export interface ApiHandler<App> {
28
+ handle(request: Request, app: App): Promise<Response | undefined>;
29
+ }
30
+ export declare function apiHandler<App>(endpoints: Record<string, Endpoint<z.ZodType, z.ZodType, App>>): ApiHandler<App> | undefined;
@@ -0,0 +1,89 @@
1
+ import { ORPCError, os } from "@orpc/server";
2
+ import { OpenAPIHandler } from "@orpc/openapi/fetch";
3
+ import { experimental_ZodSmartCoercionPlugin } from "@orpc/zod/zod4";
4
+ import { EndpointError } from "./endpoint-error.js";
5
+ // One typed function: its Zod schemas are its only types, wherever it is served.
6
+ export function endpoint(definition, handler) {
7
+ return { ...definition, handler };
8
+ }
9
+ export const servesApi = (e) => (e.serve ?? ["api"]).includes("api");
10
+ // The method and path of every endpoint served over the API, checked once: each must say both,
11
+ // stay under /api/, and use only input fields as path parameters.
12
+ export function apiRoutes(endpoints) {
13
+ const routes = {};
14
+ for (const [name, e] of Object.entries(endpoints)) {
15
+ if (!servesApi(e))
16
+ continue;
17
+ if (!e.method || !e.path)
18
+ throw new Error(`endpoint ${name} is served over the API, so it needs a method and a path`);
19
+ if (!e.path.startsWith("/api/"))
20
+ throw new Error(`endpoint ${name}'s path must start with /api/, where the Worker answers first`);
21
+ const shape = e.input.shape;
22
+ for (const [, param] of e.path.matchAll(/:([A-Za-z_][A-Za-z0-9_]*)/g)) {
23
+ if (!shape || !(param in shape))
24
+ throw new Error(`endpoint ${name}'s path has :${param}, which its input schema does not have`);
25
+ }
26
+ routes[name] = { method: e.method, path: e.path.replace(/:([A-Za-z_][A-Za-z0-9_]*)/g, "{$1}") };
27
+ }
28
+ return routes;
29
+ }
30
+ // Serves the API endpoints through oRPC, which maps path, query and body into the input, converts
31
+ // URL strings to the schema's types, and checks input and output; the app never sees it.
32
+ export function apiHandler(endpoints) {
33
+ const routes = apiRoutes(endpoints);
34
+ const names = Object.keys(routes);
35
+ if (names.length === 0)
36
+ return undefined;
37
+ const base = os.$context();
38
+ const router = Object.fromEntries(names.map((name) => {
39
+ const e = endpoints[name];
40
+ const procedure = base
41
+ .route({ method: routes[name].method, path: routes[name].path, ...(e.description && { description: e.description }) })
42
+ .input(e.input)
43
+ .output(e.output)
44
+ .handler(async ({ input, context }) => {
45
+ try {
46
+ return await e.handler(input, context.app);
47
+ }
48
+ catch (error) {
49
+ if (error instanceof EndpointError)
50
+ throw new ORPCError("ENDPOINT_ERROR", { status: error.status, message: error.message });
51
+ // A thrown Response, as requireUser throws, keeps its status and message.
52
+ if (error instanceof Response) {
53
+ const { error: message } = (await error.json().catch(() => ({})));
54
+ throw new ORPCError("ENDPOINT_ERROR", { status: error.status, message: message ?? error.statusText });
55
+ }
56
+ throw error;
57
+ }
58
+ });
59
+ return [name, procedure];
60
+ }));
61
+ const handler = new OpenAPIHandler(router, {
62
+ plugins: [new experimental_ZodSmartCoercionPlugin()],
63
+ clientInterceptors: [
64
+ async ({ next, path }) => {
65
+ try {
66
+ return await next();
67
+ }
68
+ catch (error) {
69
+ if (!(error instanceof ORPCError) || error.status >= 500)
70
+ console.error(`endpoint ${path.join(".")} failed`, error instanceof ORPCError ? (error.cause ?? error) : error);
71
+ throw error;
72
+ }
73
+ },
74
+ ],
75
+ });
76
+ return {
77
+ async handle(request, app) {
78
+ const { matched, response } = await handler.handle(request, { context: { app } });
79
+ if (!matched || !response)
80
+ return undefined;
81
+ if (response.ok)
82
+ return response;
83
+ // oRPC's error body, with the `error` every platform API error carries.
84
+ const body = (await response.json().catch(() => ({})));
85
+ return Response.json({ error: body.message ?? response.statusText, ...body }, { status: response.status });
86
+ },
87
+ };
88
+ }
89
+ //# sourceMappingURL=endpoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoints.js","sourceRoot":"","sources":["../../src/runtime/endpoints.ts"],"names":[],"mappings":"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"}
@@ -2,11 +2,16 @@ import { AUTH_PATH } from "./auth.js";
2
2
  export const PUBLIC_API = "/api/public/";
3
3
  const FORM_TYPES = ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"];
4
4
  const UNSAFE = ["POST", "PUT", "PATCH", "DELETE"];
5
+ // OAuth endpoints AI clients post forms to directly; they prove themselves with a code or token,
6
+ // never a cookie, so a forged browser form gains nothing.
7
+ const OAUTH_FORM_PATHS = ["/oauth2/token", "/oauth2/revoke", "/oauth2/introspect"].map((p) => `${AUTH_PATH}${p}`);
5
8
  // A browser sends any site's form to any other without asking, cookies included; it always
6
9
  // sends an Origin with it, so a missing or foreign one is refused.
7
10
  export function isCrossSiteForm(request, url) {
8
11
  if (!UNSAFE.includes(request.method))
9
12
  return false;
13
+ if (OAUTH_FORM_PATHS.includes(url.pathname))
14
+ return false;
10
15
  const type = request.headers.get("content-type")?.split(";", 1)[0].trim().toLowerCase() ?? "";
11
16
  if (!FORM_TYPES.includes(type))
12
17
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/runtime/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC;AAEzC,MAAM,UAAU,GAAG,CAAC,mCAAmC,EAAE,qBAAqB,EAAE,YAAY,CAAC,CAAC;AAC9F,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AAElD,2FAA2F;AAC3F,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,OAAgB,EAAE,GAAQ;IACxD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IAC/F,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC;AACtD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAChD,8FAA8F;IAC9F,OAAO,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,SAAS,GAAG,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;AACzH,CAAC;AAMD,qEAAqE;AACrE,MAAM,OAAO,GAAmC;IAC9C,CAAC,GAAG,SAAS,gBAAgB,CAAC,EAAE,OAAO;IACvC,CAAC,GAAG,SAAS,yBAAyB,CAAC,EAAE,OAAO;IAChD,CAAC,GAAG,SAAS,iBAAiB,CAAC,EAAE,IAAI;IACrC,CAAC,GAAG,SAAS,gBAAgB,CAAC,EAAE,IAAI;CACrC,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAgB,EAAE,QAAgB,EAAE,OAAgC;IACpG,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7B,IAAI,CAAC,OAAO,IAAI,CAAC,EAAE,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IAC/D,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,SAAS,CAAC;IACnE,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAwB,CAAC;QACrF,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;YAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAChF,CAAC;IACD,OAAO,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,QAAQ,IAAI,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AAC3E,CAAC"}
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/runtime/guard.ts"],"names":[],"mappings":"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"}
@@ -2,11 +2,15 @@ import { type NodePgDatabase } from "drizzle-orm/node-postgres";
2
2
  import { Pool } from "pg";
3
3
  import { type Auth } from "./auth.js";
4
4
  import { type Email, type EmailBindings } from "./email.js";
5
+ import { type Endpoint } from "./endpoints.js";
5
6
  import { type Files, type FilesBindings } from "./files.js";
6
7
  import { type RateLimiter } from "./guard.js";
8
+ import type { z } from "zod";
7
9
  import { type Live, type LiveNamespace } from "./live.js";
8
10
  import type { LivePeer } from "./live-client.js";
9
11
  export type { Auth } from "./auth.js";
12
+ export { EndpointError } from "./endpoint-error.js";
13
+ export { endpoint, type Door, type Endpoint, type EndpointDefinition, type Method } from "./endpoints.js";
10
14
  export type { Email, EmailMessage } from "./email.js";
11
15
  export type { FileEntry, Files, Folder, StoredObject } from "./files.js";
12
16
  export type { Live } from "./live.js";
@@ -22,6 +26,7 @@ export interface PlatformBindings extends EmailBindings, FilesBindings {
22
26
  AUTH_LIMIT?: RateLimiter;
23
27
  LIVE?: LiveNamespace;
24
28
  LIVE_ROOMS?: string;
29
+ MCP?: string;
25
30
  }
26
31
  export interface ExecutionContext {
27
32
  waitUntil(promise: Promise<unknown>): void;
@@ -40,20 +45,26 @@ export interface AppContext<Env, Schema extends Record<string, unknown>> {
40
45
  waitUntil(promise: Promise<unknown>): void;
41
46
  }
42
47
  export type Handler<Env, Schema extends Record<string, unknown>> = (request: Request, app: AppContext<Env, Schema>) => Response | Promise<Response>;
43
- export interface LiveOptions<Env, Schema extends Record<string, unknown>> {
48
+ export interface LiveOptions<Env, Schema extends Record<string, unknown>, Message extends z.ZodType = z.ZodType> {
49
+ message?: Message;
44
50
  canJoin?(room: string, user: User | null, app: AppContext<Env, Schema>): boolean | Promise<boolean>;
45
51
  canSend?(room: string, user: User | null, app: AppContext<Env, Schema>): boolean | Promise<boolean>;
46
- onMessage?(room: string, message: unknown, from: LivePeer | null, app: AppContext<Env, Schema>): void | Promise<void>;
52
+ onMessage?(room: string, message: z.output<Message>, from: LivePeer | null, app: AppContext<Env, Schema>): void | Promise<void>;
47
53
  }
48
54
  export interface AppOptions<Env, Schema extends Record<string, unknown>> {
49
55
  schema?: Schema;
56
+ endpoints?: Record<string, Endpoint<any, any, AppContext<Env, Schema>>>;
50
57
  screens?: {
51
58
  stylesheet?: string;
52
59
  };
53
60
  live?: LiveOptions<Env, Schema>;
54
61
  pool?: (connectionString: string) => Pool;
55
62
  }
56
- export declare function defineApp<Secrets extends object = object, Schema extends Record<string, unknown> = Record<string, never>>(handler: Handler<Secrets & PlatformBindings, Schema>, options?: AppOptions<Secrets & PlatformBindings, Schema>): {
63
+ export declare function defineApp<Secrets extends object = object, Schema extends Record<string, unknown> = Record<string, never>, E extends Record<string, Endpoint<any, any, AppContext<Secrets & PlatformBindings, Schema>>> = Record<string, never>, Message extends z.ZodType = z.ZodType>(handler: Handler<Secrets & PlatformBindings, Schema> | undefined, options?: AppOptions<Secrets & PlatformBindings, Schema> & {
64
+ endpoints?: E;
65
+ live?: LiveOptions<Secrets & PlatformBindings, Schema, Message>;
66
+ }): {
67
+ endpoints: E;
57
68
  fetch(request: Request, env: Secrets & PlatformBindings, ctx: ExecutionContext): Promise<Response>;
58
69
  LiveRoom: import("./live.js").LiveRoomClass;
59
70
  };
@@ -2,18 +2,37 @@ import { drizzle } from "drizzle-orm/node-postgres";
2
2
  import { Pool } from "pg";
3
3
  import { AUTH_PATH, createAuth } from "./auth.js";
4
4
  import { createEmail } from "./email.js";
5
+ import { apiHandler } from "./endpoints.js";
5
6
  import { createFiles } from "./files.js";
6
7
  import { isCrossSiteForm, needsSession, rateLimited } from "./guard.js";
7
- import { CLIENT_PATH, clientScript, createLive, joinRoom, LIVE_PATH, liveRoom } from "./live.js";
8
+ import { anyMessage, CLIENT_PATH, clientScript, createLive, joinRoom, LIVE_PATH, liveRoom } from "./live.js";
9
+ import { MCP_PATH, mcpChallenge, mcpUserId, serveMcp, WELL_KNOWN } from "./mcp.js";
8
10
  import { isScreen, renderScreen } from "./screens.js";
11
+ export { EndpointError } from "./endpoint-error.js";
12
+ export { endpoint } from "./endpoints.js";
13
+ function messageCheck(schema) {
14
+ if (!schema)
15
+ return anyMessage;
16
+ return (message) => {
17
+ const result = schema.safeParse(message);
18
+ return result.success ? { ok: true, value: result.data } : { ok: false, error: result.error.issues.map((i) => `${i.path.join(".") || "message"}: ${i.message}`).join("; ") };
19
+ };
20
+ }
9
21
  const defaultPool = (connectionString) => new Pool({ connectionString, max: 5 });
10
22
  const json = (body, status = 200) => Response.json(body, { status });
23
+ const notFound = () => json({ error: "not found" }, 404);
11
24
  // `Secrets` names the app's secrets, such as `defineApp<{ SESSION_SECRET: string }>`; the
12
25
  // platform's own bindings are added to it. Pass the app's tables as `schema` for a typed `app.db`.
13
- // A handler may throw a Response, as `requireUser` does, and it is sent as the answer.
26
+ // Endpoints are answered first; the handler, when given, takes every other request. A handler or
27
+ // endpoint may throw a Response, as `requireUser` does, and it is sent as the answer.
14
28
  export function defineApp(handler, options = {}) {
15
29
  const onMessage = options.live?.onMessage;
30
+ const check = messageCheck(options.live?.message);
31
+ const handle = handler ?? notFound;
32
+ const api = apiHandler(options.endpoints ?? {});
16
33
  return {
34
+ // Read by the package to generate the browser client's routes; the app's own types come from here.
35
+ endpoints: (options.endpoints ?? {}),
17
36
  async fetch(request, env, ctx) {
18
37
  const url = new URL(request.url);
19
38
  const { app, close } = createContext(request, env, ctx, options);
@@ -23,12 +42,20 @@ export function defineApp(handler, options = {}) {
23
42
  const live = await liveRoute(request, url, env, app, options);
24
43
  if (live)
25
44
  return live;
45
+ if (env.MCP === "on" && env.BETTER_AUTH_SECRET) {
46
+ const answered = await mcpRoute(request, url, env, ctx, app, options);
47
+ if (answered)
48
+ return answered;
49
+ }
26
50
  if (env.BETTER_AUTH_SECRET) {
27
51
  const platform = await platformRoute(request, url, env, app, options);
28
52
  if (platform)
29
53
  return platform;
30
54
  }
31
- return await handler(request, app);
55
+ const answered = await api?.handle(request, app);
56
+ if (answered)
57
+ return answered;
58
+ return await handle(request, app);
32
59
  }
33
60
  catch (thrown) {
34
61
  if (thrown instanceof Response)
@@ -56,10 +83,12 @@ export function defineApp(handler, options = {}) {
56
83
  close();
57
84
  }
58
85
  };
59
- }),
86
+ }, check),
60
87
  };
61
88
  }
62
- function createContext(request, env, ctx, options) {
89
+ function createContext(request, env, ctx, options,
90
+ // Set when the caller is already known, as for an MCP client signed in with a token.
91
+ knownSession) {
63
92
  const openPool = options.pool ?? defaultPool;
64
93
  let pool;
65
94
  let db;
@@ -93,10 +122,10 @@ function createContext(request, env, ctx, options) {
93
122
  }));
94
123
  },
95
124
  get live() {
96
- return (live ??= createLive(env.LIVE, env.LIVE_ROOMS === "on"));
125
+ return (live ??= createLive(env.LIVE, env.LIVE_ROOMS === "on", messageCheck(options.live?.message)));
97
126
  },
98
127
  session() {
99
- return (session ??= env.BETTER_AUTH_SECRET ? app.auth.api.getSession({ headers: request.headers }) : Promise.resolve(null));
128
+ return (session ??= knownSession ? knownSession() : env.BETTER_AUTH_SECRET ? app.auth.api.getSession({ headers: request.headers }) : Promise.resolve(null));
100
129
  },
101
130
  async requireUser() {
102
131
  const current = await app.session();
@@ -108,6 +137,33 @@ function createContext(request, env, ctx, options) {
108
137
  };
109
138
  return { app, close: () => void (pool && ctx.waitUntil(pool.end())) };
110
139
  }
140
+ // The OAuth server's routes, which exist only for MCP.
141
+ const MCP_AUTH_PATHS = ["/oauth2/", "/admin/oauth2/", "/jwks", "/.well-known/"];
142
+ // MCP for AI clients: OAuth discovery under /.well-known/, and /mcp, where each call runs as the
143
+ // user its token was issued to.
144
+ async function mcpRoute(request, url, env, ctx, app, options) {
145
+ if (url.pathname.startsWith(WELL_KNOWN))
146
+ return app.auth.handler(request);
147
+ if (url.pathname !== MCP_PATH)
148
+ return undefined;
149
+ const origin = env.APP_URL ?? url.origin;
150
+ const userId = await mcpUserId(request, app.auth, `${origin}${MCP_PATH}`);
151
+ if (!userId)
152
+ return mcpChallenge(origin);
153
+ const known = async () => {
154
+ const user = await (await app.auth.$context).internalAdapter.findUserById(userId);
155
+ return user ? { user, session: { id: "mcp", userId, token: "", expiresAt: new Date(Date.now() + 60_000), createdAt: new Date(), updatedAt: new Date() } } : null;
156
+ };
157
+ const { app: asUser, close } = createContext(request, env, ctx, options, known);
158
+ try {
159
+ if (!(await asUser.session()))
160
+ return mcpChallenge(origin);
161
+ return await serveMcp(request, asUser, env.APP_NAME ?? url.hostname, options.endpoints ?? {});
162
+ }
163
+ finally {
164
+ close();
165
+ }
166
+ }
111
167
  // Live rooms answer for themselves: the browser client, and joining a room once the app agrees.
112
168
  async function liveRoute(request, url, env, app, options) {
113
169
  if (!url.pathname.startsWith(LIVE_PATH) || env.LIVE_ROOMS !== "on" || !env.LIVE)
@@ -125,12 +181,16 @@ async function liveRoute(request, url, env, app, options) {
125
181
  // check in front of every private /api route.
126
182
  async function platformRoute(request, url, env, app, options) {
127
183
  const path = url.pathname;
184
+ if (path === "/consent" && env.MCP !== "on")
185
+ return undefined;
128
186
  if (request.method === "GET" && isScreen(path))
129
187
  return renderScreen(path, env.APP_NAME ?? url.hostname, options.screens?.stylesheet);
130
188
  if (await rateLimited(request, path, env.AUTH_LIMIT))
131
189
  return json({ error: "too many attempts; wait a minute" }, 429);
132
190
  if (path.startsWith(`${AUTH_PATH}/organization/`) && env.AUTH_ORGANIZATIONS !== "on")
133
191
  return json({ error: "not found" }, 404);
192
+ if (env.MCP !== "on" && MCP_AUTH_PATHS.some((p) => path.startsWith(`${AUTH_PATH}${p}`)))
193
+ return json({ error: "not found" }, 404);
134
194
  if (path.startsWith(`${AUTH_PATH}/`))
135
195
  return app.auth.handler(request);
136
196
  if (needsSession(path))
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
@@ -13,7 +13,7 @@ export interface Live {
13
13
  publish(room: string, message: unknown): Promise<void>;
14
14
  }
15
15
  export declare const clientScript: () => Response;
16
- export declare function createLive(namespace: LiveNamespace | undefined, enabled: boolean): Live;
16
+ export declare function createLive(namespace: LiveNamespace | undefined, enabled: boolean, check?: MessageCheck): Live;
17
17
  export interface JoinDecision {
18
18
  user: LivePeer | null;
19
19
  canJoin: boolean;
@@ -26,4 +26,12 @@ export interface LiveRoomClass {
26
26
  fetch(request: Request): Promise<Response>;
27
27
  };
28
28
  }
29
- export declare function liveRoom(onMessage: (env: unknown) => OnMessage | undefined): LiveRoomClass;
29
+ export type MessageCheck = (message: unknown) => {
30
+ ok: true;
31
+ value: unknown;
32
+ } | {
33
+ ok: false;
34
+ error: string;
35
+ };
36
+ export declare const anyMessage: MessageCheck;
37
+ export declare function liveRoom(onMessage: (env: unknown) => OnMessage | undefined, check?: MessageCheck): LiveRoomClass;
@@ -9,14 +9,17 @@ export const KEPT_MESSAGES = 500;
9
9
  const ROOM_NAME = /^[A-Za-z0-9:_.-]{1,200}$/;
10
10
  export const clientScript = () => new Response(`export ${client.toString()}\n`, { headers: { "content-type": "text/javascript; charset=utf-8", "cache-control": "public, max-age=300" } });
11
11
  const roomStub = (namespace, room) => namespace.get(namespace.idFromName(room));
12
- export function createLive(namespace, enabled) {
12
+ export function createLive(namespace, enabled, check = anyMessage) {
13
13
  return {
14
14
  async publish(room, message) {
15
15
  if (!enabled || !namespace)
16
16
  throw new Error("this app has no live rooms; set `live: true` in platform.jsonc");
17
17
  if (!ROOM_NAME.test(room))
18
18
  throw new Error(`invalid room name ${room}`);
19
- const body = JSON.stringify(message);
19
+ const checked = check(message);
20
+ if (!checked.ok)
21
+ throw new Error(`live message for ${room} does not match the app's message schema: ${checked.error}`);
22
+ const body = JSON.stringify(checked.value);
20
23
  if (body.length > MAX_MESSAGE)
21
24
  throw new Error(`live messages are limited to ${MAX_MESSAGE} bytes`);
22
25
  const response = await roomStub(namespace, room).fetch(new Request("https://room/publish", { method: "POST", headers: { "x-room": room }, body }));
@@ -50,7 +53,8 @@ export async function joinRoom(request, url, namespace, decide) {
50
53
  const since = url.searchParams.get("since");
51
54
  return roomStub(namespace, room).fetch(new Request(`https://room/join${since ? `?since=${encodeURIComponent(since)}` : ""}`, { headers }));
52
55
  }
53
- export function liveRoom(onMessage) {
56
+ export const anyMessage = (value) => ({ ok: true, value });
57
+ export function liveRoom(onMessage, check = anyMessage) {
54
58
  return class LiveRoom {
55
59
  env;
56
60
  state;
@@ -90,6 +94,10 @@ export function liveRoom(onMessage) {
90
94
  catch {
91
95
  return socket.send(JSON.stringify({ type: "error", error: "messages are JSON" }));
92
96
  }
97
+ const checked = check(data ?? null);
98
+ if (!checked.ok)
99
+ return socket.send(JSON.stringify({ type: "error", error: checked.error }));
100
+ data = checked.value;
93
101
  const seq = this.deliver(JSON.stringify(data ?? null), attachment.user, socket);
94
102
  socket.send(JSON.stringify({ type: "ack", seq }));
95
103
  const hook = onMessage(this.env);