History

cloud/local/examples: thread per-user ScopeStack through HTTP + MCP

- cloud: resolves userId from the authenticated session and builds a [userOrgScope, orgScope] stack via createScopedExecutor(userId, orgId, orgName). userId threaded through execution-stack, mcp-session, and MCP dispatch init. - cloud env refactor: deletes the lazy Proxy apps/cloud/src/env.ts in favor of cloudflare:workers env imported at call sites; adds env-augment.d.ts to type secrets not present in generated wrangler types. - cloud/server.ts: env-guarded OTEL wiring (skips instrument() when AXIOM_TOKEN absent); captures rawFetch before instrument() mutates it so dev requests still land on the Hono app. - cloud/services/db.ts: prefers DATABASE_URL over the hyperdrive proxy so local dev works without the tunnel. - vite.config.ts: devCrashGuard plugin that prints uncaught Worker errors with a stable exit. - hosts/mcp: optional debug flag surfaces verbose session logging, wired up from cloud mcp-session. - local/examples/marketing: migrated to scopes: [scope].

Rhys Sullivan committed 6 months ago

Commit d4e311e1 parent 427699c25 files · +320 −174Browse files

Showing the changes to apps/cloud/src/api (2 of 25 files). Show all

Unified · Split

2 files
  1. apps/cloud/src/api/autumn.ts +2 −2
  2. apps/cloud/src/api/protected.ts +12 −6
apps/cloud/src/api/autumn.ts+2−2
@@ -1,9 +1,9 @@
1import { env } from "cloudflare:workers";
1import { Effect } from "effect";2import { Effect } from "effect";
2import { HttpServerRequest, HttpServerResponse } from "@effect/platform";3import { HttpServerRequest, HttpServerResponse } from "@effect/platform";
3import { autumnHandler } from "autumn-js/backend";4import { autumnHandler } from "autumn-js/backend";
4 5
5import { WorkOSAuth } from "../auth/workos";6import { WorkOSAuth } from "../auth/workos";
6import { server } from "../env";
7import { HttpResponseError, isServerError, toErrorServerResponse } from "./error-response";7import { HttpResponseError, isServerError, toErrorServerResponse } from "./error-response";
8import { SharedServices } from "./layers";8import { SharedServices } from "./layers";
9 9
@@ -59,7 +59,7 @@ export const AutumnApiApp = Effect.gen(function* () { · 49 unmodified lines
59 email: session.email,59 email: session.email,
60 },60 },
61 clientOptions: {61 clientOptions: {
62 secretKey: server.AUTUMN_SECRET_KEY,62 secretKey: env.AUTUMN_SECRET_KEY ?? "",
63 },63 },
64 pathPrefix: "/autumn",64 pathPrefix: "/autumn",
65 }),65 }),
apps/cloud/src/api/protected.ts+12−6
@@ -27,12 +27,18 @@ const lookupOrgForRequest = (request: HttpServerRequest.HttpServerRequest) => · 26 unmodified lines
27 const session = yield* workos.authenticateRequest(webRequest);27 const session = yield* workos.authenticateRequest(webRequest);
28 if (!session || !session.organizationId) return null;28 if (!session || !session.organizationId) return null;
29 29
30 return yield* authorizeOrganization(session.userId, session.organizationId);30 const org = yield* authorizeOrganization(session.userId, session.organizationId);
31 if (!org) return null;
32 return { org, userId: session.userId };
31 });33 });
32 34
33const createProtectedApp = (organizationId: string, organizationName: string) =>35const createProtectedApp = (userId: string, organizationId: string, organizationName: string) =>
34 Effect.gen(function* () {36 Effect.gen(function* () {
35 const { executor, engine } = yield* makeExecutionStack(organizationId, organizationName);37 const { executor, engine } = yield* makeExecutionStack(
38 userId,
39 organizationId,
40 organizationName,
41 );
36 42
37 const requestServices = Layer.mergeAll(43 const requestServices = Layer.mergeAll(
38 Layer.succeed(ExecutorService, executor),44 Layer.succeed(ExecutorService, executor),
@@ -58,8 +64,8 @@ const createProtectedApp = (organizationId: string, organizationName: string) => · 19 unmodified lines
58 64
59export const ProtectedApiApp = Effect.gen(function* () {65export const ProtectedApiApp = Effect.gen(function* () {
60 const request = yield* HttpServerRequest.HttpServerRequest;66 const request = yield* HttpServerRequest.HttpServerRequest;
61 const org = yield* lookupOrgForRequest(request);67 const session = yield* lookupOrgForRequest(request);
62 if (!org) {68 if (!session) {
63 return yield* Effect.fail(69 return yield* Effect.fail(
64 new HttpResponseError({70 new HttpResponseError({
65 status: 403,71 status: 403,
@@ -69,7 +75,7 @@ export const ProtectedApiApp = Effect.gen(function* () { · 3 unmodified lines
69 );75 );
70 }76 }
71 77
72 const app = yield* createProtectedApp(org.id, org.name);78 const app = yield* createProtectedApp(session.userId, session.org.id, session.org.name);
73 return yield* app;79 return yield* app;
74}).pipe(80}).pipe(
75 Effect.provide(SharedServices),81 Effect.provide(SharedServices),