History

Move product access rules out of the SDK

Rhys Sullivan committed 1 month ago

Commit c676e561 parent a72e51d161 files · +3935 −867Browse files

Showing the changes to packages/plugins/openapi/src (15 of 161 files). Show all

Unified · Split

15 files
  1. packages/plugins/openapi/src/providers/google/spec-format-adapter.test.ts +4 −0
  2. packages/plugins/openapi/src/sdk/configure.test.ts +25 −8
  3. packages/plugins/openapi/src/sdk/form-urlencoded-body.test.ts +22 −23
  4. packages/plugins/openapi/src/sdk/health-check-redaction.test.ts +2 −0
  5. packages/plugins/openapi/src/sdk/multi-scope-bearer.test.ts +4 −1
  6. packages/plugins/openapi/src/sdk/non-json-body.test.ts +106 −35
  7. packages/plugins/openapi/src/sdk/plugin.test.ts +104 −35
  8. packages/plugins/openapi/src/sdk/real-specs.test.ts +2 −0
  9. packages/plugins/openapi/src/sdk/response-body-timeout.test.ts +4 −1
  10. packages/plugins/openapi/src/sdk/response-headers-timeout.test.ts +4 −1
  11. packages/plugins/openapi/src/sdk/spec-blob.test.ts +15 −6
  12. packages/plugins/openapi/src/sdk/spec-overrides-lifecycle.test.ts +10 −3
  13. packages/plugins/openapi/src/sdk/streaming-response.test.ts +7 −2
  14. packages/plugins/openapi/src/sdk/tool-row-projection.test.ts +4 −1
  15. packages/plugins/openapi/src/sdk/upstream-failures.test.ts +8 −3
packages/plugins/openapi/src/providers/google/spec-format-adapter.test.ts+4−0
@@ -9,6 +9,7 @@ import type { AuthenticationInput } from "@executor-js/plugin-openapi"; · 8 unmodified lines
99
1010 import { deriveGoogleDiscoveryIdentity, googleDiscoveryAdapter } from "./spec-format-adapter";
1111 import { googleCatalog } from "./presets";
12+import { testAccess } from "@executor-js/product-access/testing";
1213
1314 const TASKS_URL = "https://www.googleapis.com/discovery/v1/apis/tasks/v1/rest";
1415 const GMAIL_URL = "https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest";
@@ -179,6 +180,7 @@ it.effect("adds a Google Discovery URL through the OpenAPI plugin with derived i · 164 unmodified lines
179180 Effect.gen(function* () {
180181 const executor = yield* createExecutor(
181182 makeTestConfig({
183+ access: testAccess.member(),
182184 plugins: [
183185 openApiPlugin({
184186 httpClientLayer: discoveryHttpClientLayer,
@@ -211,6 +213,7 @@ it.effect( · 26 unmodified lines
211213 );
212214 const executor = yield* createExecutor(
213215 makeTestConfig({
216+ access: testAccess.member(),
214217 plugins: [
215218 openApiPlugin({
216219 httpClientLayer: discoveryHttpClientLayer,
@@ -257,6 +260,7 @@ it.effect("preserves a Google preset's full consumer consent boundary when refre · 40 unmodified lines
257260 );
258261 const executor = yield* createExecutor(
259262 makeTestConfig({
263+ access: testAccess.member(),
260264 plugins: [
261265 openApiPlugin({
262266 httpClientLayer: gmailDiscoveryHttpClientLayer,
packages/plugins/openapi/src/sdk/configure.test.ts+25−8
@@ -35,6 +35,7 @@ import { · 34 unmodified lines
3535 serveOpenApiHttpApiTestServer,
3636 unwrapInvocation,
3737 } from "../testing";
38+import { testAccess } from "@executor-js/product-access/testing";
3839
3940 const testPlugins = (httpClientLayer = FetchHttpClient.layer) =>
4041 [openApiPlugin({ httpClientLayer }), memoryCredentialsPlugin()] as const;
@@ -90,7 +91,9 @@ describe("OpenAPI Plugin — configure (custom auth method)", () => { · 49 unmodified lines
9091 it.effect("adds a custom apiKey method and getConfig reflects it", () =>
9192 Effect.scoped(
9293 Effect.gen(function* () {
93− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
94+ const executor = yield* createExecutor(
95+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
96+ );
9497
9598 yield* executor.openapi.addSpec({
9699 spec: { kind: "blob", value: specText() },
@@ -119,7 +122,9 @@ describe("OpenAPI Plugin — configure (custom auth method)", () => { · 22 unmodified lines
119122 it.effect("appends to an existing spec-derived template without dropping entries", () =>
120123 Effect.scoped(
121124 Effect.gen(function* () {
122− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
125+ const executor = yield* createExecutor(
126+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
127+ );
123128
124129 const seedTemplate: AuthenticationInput = {
125130 slug: "seed",
@@ -145,7 +150,9 @@ describe("OpenAPI Plugin — configure (custom auth method)", () => { · 19 unmodified lines
145150 it.effect("generates a custom_<id> slug for a method submitted without one", () =>
146151 Effect.scoped(
147152 Effect.gen(function* () {
148− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
153+ const executor = yield* createExecutor(
154+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
155+ );
149156
150157 yield* executor.openapi.addSpec({
151158 spec: { kind: "blob", value: specText() },
@@ -167,7 +174,9 @@ describe("OpenAPI Plugin — configure (custom auth method)", () => { · 15 unmodified lines
167174 it.effect("dedupes: a matching slug replaces in place; two slugless get distinct slugs", () =>
168175 Effect.scoped(
169176 Effect.gen(function* () {
170− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
177+ const executor = yield* createExecutor(
178+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
179+ );
171180
172181 yield* executor.openapi.addSpec({
173182 spec: { kind: "blob", value: specText() },
@@ -208,7 +217,9 @@ describe("OpenAPI Plugin — configure (custom auth method)", () => { · 34 unmodified lines
208217 it.effect("replace mode overwrites the auth template array", () =>
209218 Effect.scoped(
210219 Effect.gen(function* () {
211− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
220+ const executor = yield* createExecutor(
221+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
222+ );
212223
213224 const seedTemplate: AuthenticationInput = {
214225 slug: "seed",
@@ -236,7 +247,9 @@ describe("OpenAPI Plugin — configure (custom auth method)", () => { · 21 unmodified lines
236247 Effect.scoped(
237248 Effect.gen(function* () {
238249 const server = yield* servePluginTestApi();
239− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
250+ const executor = yield* createExecutor(
251+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
252+ );
240253
241254 yield* executor.openapi.addSpec({
242255 spec: { kind: "blob", value: server.specJson },
@@ -272,7 +285,9 @@ describe("OpenAPI Plugin — configure (custom auth method)", () => { · 29 unmodified lines
272285 Effect.scoped(
273286 Effect.gen(function* () {
274287 const server = yield* servePluginTestApi();
275− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
288+ const executor = yield* createExecutor(
289+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
290+ );
276291
277292 yield* executor.openapi.addSpec({
278293 spec: { kind: "blob", value: server.specJson },
@@ -320,7 +335,9 @@ describe("OpenAPI Plugin — configure (custom auth method)", () => { · 41 unmodified lines
320335 it.effect("getConfig returns null for an unknown integration", () =>
321336 Effect.scoped(
322337 Effect.gen(function* () {
323− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
338+ const executor = yield* createExecutor(
339+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
340+ );
324341 expect(yield* executor.openapi.getConfig("nope")).toBeNull();
325342 }),
326343 ),
packages/plugins/openapi/src/sdk/form-urlencoded-body.test.ts+22−23
@@ -30,6 +30,7 @@ import { · 29 unmodified lines
3030 } from "@executor-js/plugin-openapi/testing";
3131
3232 import { openApiPlugin } from "./plugin";
33+import { testAccess } from "@executor-js/product-access/testing";
3334
3435 type Captured = {
3536 contentType: string;
@@ -76,30 +77,28 @@ const plugins = [ · 40 unmodified lines
7677 memoryCredentialsPlugin(),
7778 ] as const;
7879
79−layer(
80− makeTestWorkspaceLayer({
81− plugins,
82− }),
83− { timeout: "15 seconds" },
84−)("OpenAPI non-JSON request body serialization", (it) => {
85− it.effect("form-urlencoded object body is properly encoded (no '[object Object]')", () =>
86− Effect.gen(function* () {
87− const { server, captured } = yield* startEchoServer();
88− const { config } = yield* TestWorkspace;
89− const executor = yield* createExecutor({ ...config, plugins });
80+layer(makeTestWorkspaceLayer({ access: testAccess.member(), plugins }), { timeout: "15 seconds" })(
81+ "OpenAPI non-JSON request body serialization",
82+ (it) => {
83+ it.effect("form-urlencoded object body is properly encoded (no '[object Object]')", () =>
84+ Effect.gen(function* () {
85+ const { server, captured } = yield* startEchoServer();
86+ const { config } = yield* TestWorkspace;
87+ const executor = yield* createExecutor({ ...config, plugins });
9088
91− const conn = yield* addOpenApiTestConnection(executor, server, { slug: "form" });
89+ const conn = yield* addOpenApiTestConnection(executor, server, { slug: "form" });
9290
93− yield* executor.execute(conn.address("forms.submit"), {
94− body: { name: "Acme", email: "a@b.com" },
95− });
91+ yield* executor.execute(conn.address("forms.submit"), {
92+ body: { name: "Acme", email: "a@b.com" },
93+ });
9694
97− expect(captured.contentType).toBe("application/x-www-form-urlencoded");
98− expect(captured.body).not.toBe("[object Object]");
95+ expect(captured.contentType).toBe("application/x-www-form-urlencoded");
96+ expect(captured.body).not.toBe("[object Object]");
9997
100− const parsed = new URLSearchParams(captured.body);
101− expect(parsed.get("name")).toBe("Acme");
102− expect(parsed.get("email")).toBe("a@b.com");
103− }),
104− );
105−});
98+ const parsed = new URLSearchParams(captured.body);
99+ expect(parsed.get("name")).toBe("Acme");
100+ expect(parsed.get("email")).toBe("a@b.com");
101+ }),
102+ );
103+ },
104+);
packages/plugins/openapi/src/sdk/health-check-redaction.test.ts+2−0
@@ -34,6 +34,7 @@ import { variable } from "@executor-js/sdk/http-auth"; · 33 unmodified lines
3434
3535 import { serveOpenApiHttpApiTestServer } from "../testing";
3636 import { openApiPlugin } from "./plugin";
37+import { testAccess } from "@executor-js/product-access/testing";
3738
3839 /** The credential the connection authenticates with. Longer than the sample's
3940 * 120-char value cap on purpose: truncating before scrubbing would leave a
@@ -84,6 +85,7 @@ const withProbe = <A, E, R>( · 44 unmodified lines
8485 });
8586 const executor = yield* createExecutor(
8687 makeTestConfig({
88+ access: testAccess.member(),
8789 plugins: [
8890 openApiPlugin({ httpClientLayer: FetchHttpClient.layer }),
8991 memoryCredentialsPlugin(),
packages/plugins/openapi/src/sdk/multi-scope-bearer.test.ts+4−1
@@ -37,6 +37,7 @@ import { · 36 unmodified lines
3737
3838 import { openApiPlugin } from "./plugin";
3939 import { type AuthenticationInput } from "./types";
40+import { testAccess } from "@executor-js/product-access/testing";
4041
4142 // ---------------------------------------------------------------------------
4243 // Test API — a single endpoint that echoes the Authorization header so the
@@ -86,7 +87,9 @@ describe("OpenAPI owner-isolated bearer", () => { · 43 unmodified lines
8687 Effect.scoped(
8788 Effect.gen(function* () {
8889 const server = yield* serveVercel();
89− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
90+ const executor = yield* createExecutor(
91+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
92+ );
9093
9194 // Admin uploads the spec once; the integration declares a bearer
9295 // template but no token value.
packages/plugins/openapi/src/sdk/non-json-body.test.ts+106−35
@@ -32,6 +32,7 @@ import { · 31 unmodified lines
3232 } from "@executor-js/plugin-openapi/testing";
3333
3434 import { openApiPlugin } from "./plugin";
35+import { testAccess } from "@executor-js/product-access/testing";
3536
3637 const JsonNameBody = Schema.fromJsonString(
3738 Schema.Struct({
@@ -172,7 +173,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 134 unmodified lines
172173 payload: ObjectBody.pipe(HttpApiSchema.asMultipart()),
173174 });
174175
175− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
176+ const executor = yield* createExecutor(
177+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
178+ );
176179
177180 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "mp" });
178181
@@ -222,7 +225,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 43 unmodified lines
222225 ),
223226 });
224227
225− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
228+ const executor = yield* createExecutor(
229+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
230+ );
226231 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "paperless" });
227232
228233 const schema = yield* executor.tools.schema(conn.address("body.upload"));
@@ -298,7 +303,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 69 unmodified lines
298303 ),
299304 });
300305
301− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
306+ const executor = yield* createExecutor(
307+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
308+ );
302309 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "pages" });
303310
304311 const schema = yield* executor.tools.schema(conn.address("body.uploadPages"));
@@ -378,7 +385,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 73 unmodified lines
378385 }),
379386 });
380387
381− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
388+ const executor = yield* createExecutor(
389+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
390+ );
382391 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "broken" });
383392
384393 const exit = yield* executor
@@ -424,7 +433,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 39 unmodified lines
424433 }),
425434 });
426435
427− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
436+ const executor = yield* createExecutor(
437+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
438+ );
428439 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "notes" });
429440
430441 // The rewrite is scoped to multipart bodies: a JSON body keeps its
@@ -465,7 +476,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 34 unmodified lines
465476 }),
466477 });
467478
468− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
479+ const executor = yield* createExecutor(
480+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
481+ );
469482 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "notes-jsonapi" });
470483
471484 yield* executor.execute(conn.address("body.createNote"), {
@@ -511,7 +524,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 39 unmodified lines
511524 }),
512525 });
513526
514− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
527+ const executor = yield* createExecutor(
528+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
529+ );
515530 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "mixed" });
516531
517532 const schema = yield* executor.tools.schema(conn.address("body.uploadMixed"));
@@ -564,7 +579,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 46 unmodified lines
564579 },
565580 });
566581
567− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
582+ const executor = yield* createExecutor(
583+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
584+ );
568585 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "reffed" });
569586
570587 // Documented limitation: component schemas are carried through
@@ -584,7 +601,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 13 unmodified lines
584601 payload: Schema.String.pipe(HttpApiSchema.asText({ contentType: "application/xml" })),
585602 });
586603
587− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
604+ const executor = yield* createExecutor(
605+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
606+ );
588607
589608 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "xml" });
590609
@@ -603,7 +622,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 12 unmodified lines
603622 transformSpec: replaceRequestBodyContent("/submit", "post", contentFor("text/xml")),
604623 });
605624
606− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
625+ const executor = yield* createExecutor(
626+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
627+ );
607628
608629 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "tx" });
609630
@@ -622,7 +643,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 12 unmodified lines
622643 payload: Schema.String.pipe(HttpApiSchema.asText()),
623644 });
624645
625− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
646+ const executor = yield* createExecutor(
647+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
648+ );
626649
627650 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "tp" });
628651
@@ -639,7 +662,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 10 unmodified lines
639662 payload: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array()),
640663 });
641664
642− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
665+ const executor = yield* createExecutor(
666+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
667+ );
643668
644669 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "bin" });
645670
@@ -658,7 +683,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 12 unmodified lines
658683 payload: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array()),
659684 });
660685
661− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
686+ const executor = yield* createExecutor(
687+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
688+ );
662689
663690 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "bin_b64" });
664691
@@ -677,7 +704,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 12 unmodified lines
677704 payload: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array()),
678705 });
679706
680− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
707+ const executor = yield* createExecutor(
708+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
709+ );
681710
682711 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "bin_b64_bad" });
683712
@@ -699,7 +728,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 15 unmodified lines
699728 payload: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array()),
700729 });
701730
702− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
731+ const executor = yield* createExecutor(
732+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
733+ );
703734
704735 const conn = yield* addOpenApiTestConnection(executor, server, {
705736 slug: "bin_nested_b64_bad",
@@ -723,7 +754,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 17 unmodified lines
723754 payload: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array()),
724755 });
725756
726− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
757+ const executor = yield* createExecutor(
758+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
759+ );
727760
728761 const conn = yield* addOpenApiTestConnection(executor, server, {
729762 slug: "bin_b64_missing",
@@ -743,7 +776,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 13 unmodified lines
743776 payload: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array()),
744777 });
745778
746− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
779+ const executor = yield* createExecutor(
780+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
781+ );
747782
748783 const conn = yield* addOpenApiTestConnection(executor, server, {
749784 slug: "bin_object_body",
@@ -767,7 +802,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 17 unmodified lines
767802 payload: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array()),
768803 });
769804
770− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
805+ const executor = yield* createExecutor(
806+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
807+ );
771808
772809 const conn = yield* addOpenApiTestConnection(executor, server, {
773810 slug: "bin_string_body",
@@ -837,7 +874,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 63 unmodified lines
837874 }),
838875 });
839876
840− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
877+ const executor = yield* createExecutor(
878+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
879+ );
841880 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "gmail" });
842881
843882 const schema = yield* executor.tools.schema(conn.address("gmail.getAttachment"));
@@ -921,7 +960,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 77 unmodified lines
921960 }),
922961 });
923962
924− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
963+ const executor = yield* createExecutor(
964+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
965+ );
925966 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "gmail_text" });
926967
927968 const result = yield* executor.execute(conn.address("gmailText.getAttachment"), {
@@ -989,7 +1030,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 61 unmodified lines
9891030 }),
9901031 });
9911032
992− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1033+ const executor = yield* createExecutor(
1034+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1035+ );
9931036 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "zip_attachment" });
9941037
9951038 const result = yield* executor.execute(conn.address("zipAttachment.getAttachment"), {
@@ -1107,7 +1150,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 111 unmodified lines
11071150 ),
11081151 });
11091152
1110− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1153+ const executor = yield* createExecutor(
1154+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1155+ );
11111156 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "gmail_meta" });
11121157
11131158 const result = yield* executor.execute(conn.address("gmailMeta.getAttachment"), {
@@ -1156,7 +1201,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 42 unmodified lines
11561201 }),
11571202 });
11581203
1159− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1204+ const executor = yield* createExecutor(
1205+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1206+ );
11601207 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "files" });
11611208
11621209 const schema = yield* executor.tools.schema(conn.address("files.download"));
@@ -1210,7 +1257,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 47 unmodified lines
12101257 }),
12111258 });
12121259
1213− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1260+ const executor = yield* createExecutor(
1261+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1262+ );
12141263 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "files" });
12151264
12161265 const result = yield* executor.execute(conn.address("files.download"), {
@@ -1247,7 +1296,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 30 unmodified lines
12471296 payload: multiContentPayload,
12481297 });
12491298
1250− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1299+ const executor = yield* createExecutor(
1300+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1301+ );
12511302
12521303 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "mc" });
12531304
@@ -1265,7 +1316,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 11 unmodified lines
12651316 payload: multiContentPayload,
12661317 });
12671318
1268− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1319+ const executor = yield* createExecutor(
1320+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1321+ );
12691322
12701323 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "mc2" });
12711324
@@ -1295,7 +1348,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 23 unmodified lines
12951348 }),
12961349 });
12971350
1298− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1351+ const executor = yield* createExecutor(
1352+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1353+ );
12991354
13001355 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "mc_b64" });
13011356
@@ -1322,7 +1377,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 20 unmodified lines
13221377 }),
13231378 });
13241379
1325− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1380+ const executor = yield* createExecutor(
1381+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1382+ );
13261383
13271384 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "mc_b64_bad_ct" });
13281385
@@ -1352,7 +1409,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 23 unmodified lines
13521409 },
13531410 }),
13541411 });
1355− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1412+ const executor = yield* createExecutor(
1413+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1414+ );
13561415
13571416 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "mc_b64_schema" });
13581417
@@ -1375,7 +1434,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 16 unmodified lines
13751434 const { server } = yield* startEchoServer({
13761435 payload: multiContentPayload,
13771436 });
1378− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1437+ const executor = yield* createExecutor(
1438+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1439+ );
13791440
13801441 const conn = yield* addOpenApiTestConnection(executor, server, {
13811442 slug: "mc3",
@@ -1404,7 +1465,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 22 unmodified lines
14041465 const { server } = yield* startEchoServer({
14051466 payload: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array()),
14061467 });
1407− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1468+ const executor = yield* createExecutor(
1469+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1470+ );
14081471
14091472 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "bin_schema" });
14101473
@@ -1450,7 +1513,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 39 unmodified lines
14501513 ),
14511514 });
14521515
1453− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1516+ const executor = yield* createExecutor(
1517+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1518+ );
14541519
14551520 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "mpe" });
14561521
@@ -1492,7 +1557,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 35 unmodified lines
14921557 ),
14931558 });
14941559
1495− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1560+ const executor = yield* createExecutor(
1561+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1562+ );
14961563
14971564 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "fe" });
14981565
@@ -1523,7 +1590,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 24 unmodified lines
15231590 ),
15241591 });
15251592
1526− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1593+ const executor = yield* createExecutor(
1594+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1595+ );
15271596
15281597 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "fd" });
15291598
@@ -1550,7 +1619,9 @@ describe("OpenAPI non-JSON request body dispatch", () => { · 20 unmodified lines
15501619 ),
15511620 });
15521621
1553− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1622+ const executor = yield* createExecutor(
1623+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1624+ );
15541625
15551626 // No encoding → OAS3 defaults: style=form, explode=true.
15561627 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "fdx" });
packages/plugins/openapi/src/sdk/plugin.test.ts+104−35
@@ -49,6 +49,7 @@ import { · 48 unmodified lines
4949 serveOpenApiHttpApiTestServer,
5050 unwrapInvocation,
5151 } from "../testing";
52+import { testAccess } from "@executor-js/product-access/testing";
5253
5354 const TOOL_ERROR_TYPESCRIPT =
5455 "{ code: string; message: string; status?: number; details?: unknown; retryable?: boolean }";
@@ -393,7 +394,9 @@ describe("OpenAPI Plugin", () => { · 338 unmodified lines
393394 Effect.gen(function* () {
394395 const server = yield* servePluginTestApi();
395396
396− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
397+ const executor = yield* createExecutor(
398+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
399+ );
397400
398401 const preview = yield* executor.openapi.previewSpec(server.specJson);
399402
@@ -408,7 +411,10 @@ describe("OpenAPI Plugin", () => { · 8 unmodified lines
408411 Effect.gen(function* () {
409412 const server = yield* serveOAuthDiscoverableOpenApiSpec();
410413 const executor = yield* createExecutor(
411− makeTestConfig({ plugins: testPlugins(server.httpClientLayer) }),
414+ makeTestConfig({
415+ access: testAccess.member(),
416+ plugins: testPlugins(server.httpClientLayer),
417+ }),
412418 );
413419
414420 const preview = yield* executor.openapi.previewSpec(server.url("/api/schema/"));
@@ -456,7 +462,9 @@ describe("OpenAPI Plugin", () => { · 41 unmodified lines
456462
457463 it.effect("exposes static openapi executor control tools via execute", () =>
458464 Effect.gen(function* () {
459− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
465+ const executor = yield* createExecutor(
466+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
467+ );
460468
461469 // v2: static control tools are NOT part of `tools.list()` (that's the
462470 // persisted per-connection catalog) and aren't `tools.schema()`-resolvable;
@@ -473,7 +481,9 @@ describe("OpenAPI Plugin", () => { · 10 unmodified lines
473481
474482 it.effect("invokes static previewSpec through executor.execute", () =>
475483 Effect.gen(function* () {
476− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
484+ const executor = yield* createExecutor(
485+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
486+ );
477487
478488 const preview = unwrapInvocation(
479489 yield* executor.execute(ToolAddress.make("executor.openapi.previewSpec"), {
@@ -495,7 +505,9 @@ describe("OpenAPI Plugin", () => { · 15 unmodified lines
495505
496506 it.effect("invokes static addSpec through executor.execute", () =>
497507 Effect.gen(function* () {
498− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
508+ const executor = yield* createExecutor(
509+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
510+ );
499511
500512 const result = unwrapInvocation(
501513 yield* executor.execute(ToolAddress.make("executor.openapi.addSpec"), {
@@ -517,7 +529,9 @@ describe("OpenAPI Plugin", () => { · 15 unmodified lines
517529 Effect.scoped(
518530 Effect.gen(function* () {
519531 const specServer = yield* serveMutableOpenApiSpecTestServer({ initialApi: TestApi });
520− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
532+ const executor = yield* createExecutor(
533+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
534+ );
521535
522536 yield* executor.openapi.addSpec({
523537 spec: { kind: "url", url: specServer.specUrl },
@@ -565,7 +579,10 @@ describe("OpenAPI Plugin", () => { · 41 unmodified lines
565579
566580 it.effect("static previewSpec returns actionable tool failures", () =>
567581 Effect.gen(function* () {
568− const config = makeTestConfig({ plugins: [openApiPlugin()] as const });
582+ const config = makeTestConfig({
583+ access: testAccess.member(),
584+ plugins: [openApiPlugin()] as const,
585+ });
569586 const executor = yield* createExecutor(config);
570587
571588 const result = yield* executor.execute(ToolAddress.make("executor.openapi.previewSpec"), {
@@ -587,7 +604,7 @@ describe("OpenAPI Plugin", () => { · 15 unmodified lines
587604 it.effect("requires approval before adding an integration through the runtime tool", () =>
588605 Effect.gen(function* () {
589606 const executor = yield* createExecutor(
590− makeTestConfig({ plugins: [openApiPlugin()] as const }),
607+ makeTestConfig({ access: testAccess.member(), plugins: [openApiPlugin()] as const }),
591608 );
592609
593610 const declined = yield* executor
@@ -607,7 +624,9 @@ describe("OpenAPI Plugin", () => { · 13 unmodified lines
607624 Effect.scoped(
608625 Effect.gen(function* () {
609626 const server = yield* servePluginTestApi();
610− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
627+ const executor = yield* createExecutor(
628+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
629+ );
611630
612631 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "test" });
613632
@@ -625,7 +644,9 @@ describe("OpenAPI Plugin", () => { · 11 unmodified lines
625644 Effect.scoped(
626645 Effect.gen(function* () {
627646 const server = yield* servePluginTestApi();
628− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
647+ const executor = yield* createExecutor(
648+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
649+ );
629650
630651 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "test" });
631652
@@ -642,7 +663,9 @@ describe("OpenAPI Plugin", () => { · 10 unmodified lines
642663 Effect.scoped(
643664 Effect.gen(function* () {
644665 const server = yield* servePluginTestApi();
645− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
666+ const executor = yield* createExecutor(
667+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
668+ );
646669
647670 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "test" });
648671 const calls = { count: 0 };
@@ -671,7 +694,9 @@ describe("OpenAPI Plugin", () => { · 22 unmodified lines
671694 Effect.scoped(
672695 Effect.gen(function* () {
673696 const server = yield* servePluginTestApi();
674− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
697+ const executor = yield* createExecutor(
698+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
699+ );
675700
676701 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "test" });
677702 const calls = { count: 0 };
@@ -705,7 +730,9 @@ describe("OpenAPI Plugin", () => { · 27 unmodified lines
705730 Effect.scoped(
706731 Effect.gen(function* () {
707732 const server = yield* servePluginTestApi();
708− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
733+ const executor = yield* createExecutor(
734+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
735+ );
709736
710737 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "test" });
711738 const calls = { count: 0 };
@@ -738,7 +765,9 @@ describe("OpenAPI Plugin", () => { · 26 unmodified lines
738765 Effect.scoped(
739766 Effect.gen(function* () {
740767 const server = yield* servePluginTestApi();
741− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
768+ const executor = yield* createExecutor(
769+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
770+ );
742771
743772 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "test" });
744773 const calls = { count: 0 };
@@ -771,7 +800,9 @@ describe("OpenAPI Plugin", () => { · 26 unmodified lines
771800 Effect.scoped(
772801 Effect.gen(function* () {
773802 const server = yield* servePluginTestApi();
774− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
803+ const executor = yield* createExecutor(
804+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
805+ );
775806
776807 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "test" });
777808
@@ -812,7 +843,9 @@ describe("OpenAPI Plugin", () => { · 34 unmodified lines
812843 Effect.scoped(
813844 Effect.gen(function* () {
814845 const server = yield* servePluginTestApi();
815− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
846+ const executor = yield* createExecutor(
847+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
848+ );
816849
817850 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "test" });
818851
@@ -829,7 +862,9 @@ describe("OpenAPI Plugin", () => { · 10 unmodified lines
829862 Effect.scoped(
830863 Effect.gen(function* () {
831864 const server = yield* servePluginTestApi();
832− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
865+ const executor = yield* createExecutor(
866+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
867+ );
833868
834869 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "test" });
835870 const failure = yield* executor
@@ -853,7 +888,9 @@ describe("OpenAPI Plugin", () => { · 17 unmodified lines
853888 Effect.scoped(
854889 Effect.gen(function* () {
855890 const server = yield* servePluginTestApi();
856− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
891+ const executor = yield* createExecutor(
892+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
893+ );
857894 const multiServer = {
858895 ...server,
859896 specJson: makeOpenApiTestSpecJson(TestApi, {
@@ -889,7 +926,9 @@ describe("OpenAPI Plugin", () => { · 29 unmodified lines
889926 const server = yield* serveOpenApiEchoTestServer({
890927 transformSpec: withEchoCookieParameter,
891928 });
892− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
929+ const executor = yield* createExecutor(
930+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
931+ );
893932 const conn = yield* addOpenApiTestConnection(executor, server, {
894933 slug: "cookie_params",
895934 headers: { Cookie: "configured=yes" },
@@ -923,7 +962,9 @@ describe("OpenAPI Plugin", () => { · 27 unmodified lines
923962 const server = yield* serveOpenApiEchoTestServer({
924963 transformSpec: withEchoCookieParameter,
925964 });
926− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
965+ const executor = yield* createExecutor(
966+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
967+ );
927968 const conn = yield* addOpenApiTestConnection(executor, server, {
928969 slug: "cookie_unknown",
929970 });
@@ -951,7 +992,9 @@ describe("OpenAPI Plugin", () => { · 21 unmodified lines
951992 Effect.scoped(
952993 Effect.gen(function* () {
953994 const server = yield* servePluginTestApi();
954− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
995+ const executor = yield* createExecutor(
996+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
997+ );
955998
956999 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "records" });
9571000
@@ -980,7 +1023,9 @@ describe("OpenAPI Plugin", () => { · 22 unmodified lines
9801023 Effect.scoped(
9811024 Effect.gen(function* () {
9821025 const server = yield* servePluginTestApi();
983− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1026+ const executor = yield* createExecutor(
1027+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1028+ );
9841029
9851030 yield* executor.openapi.addSpec({
9861031 spec: { kind: "blob", value: server.specJson },
@@ -1012,7 +1057,9 @@ describe("OpenAPI Plugin", () => { · 25 unmodified lines
10121057 Effect.scoped(
10131058 Effect.gen(function* () {
10141059 const server = yield* servePluginTestApi();
1015− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1060+ const executor = yield* createExecutor(
1061+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1062+ );
10161063
10171064 yield* executor.openapi.addSpec({
10181065 spec: { kind: "blob", value: server.specJson },
@@ -1044,7 +1091,9 @@ describe("OpenAPI Plugin", () => { · 25 unmodified lines
10441091 Effect.scoped(
10451092 Effect.gen(function* () {
10461093 const server = yield* servePluginTestApi();
1047− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1094+ const executor = yield* createExecutor(
1095+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1096+ );
10481097
10491098 // The spec declares bearer auth; the caller passes NO template — the
10501099 // agentic add path (MCP/API) does exactly this. Without server-side
@@ -1097,7 +1146,9 @@ describe("OpenAPI Plugin", () => { · 46 unmodified lines
10971146 Effect.scoped(
10981147 Effect.gen(function* () {
10991148 const server = yield* servePluginTestApi();
1100− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1149+ const executor = yield* createExecutor(
1150+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1151+ );
11011152
11021153 // No baseUrl override: the spec declares `servers`, so the host is
11031154 // resolved per call from the operation's servers rather than baked into
@@ -1127,7 +1178,9 @@ describe("OpenAPI Plugin", () => { · 23 unmodified lines
11271178 Effect.scoped(
11281179 Effect.gen(function* () {
11291180 const server = yield* servePluginTestApi();
1130− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1181+ const executor = yield* createExecutor(
1182+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1183+ );
11311184
11321185 // The add page sends [] when the user deletes every detected method.
11331186 // That intent must survive — deriving methods back from the spec here
@@ -1158,7 +1211,9 @@ describe("OpenAPI Plugin", () => { · 24 unmodified lines
11581211
11591212 it.effect("addSpec accepts Graph-sized OpenAPI blobs", () =>
11601213 Effect.gen(function* () {
1161− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1214+ const executor = yield* createExecutor(
1215+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1216+ );
11621217 const largeDescription = "x".repeat(36 * 1024 * 1024);
11631218
11641219 const added = yield* executor.openapi.addSpec({
@@ -1191,7 +1246,9 @@ paths: · 26 unmodified lines
11911246 "addSpec accepts Microsoft Graph-scale operation catalogs from one spec",
11921247 () =>
11931248 Effect.gen(function* () {
1194− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1249+ const executor = yield* createExecutor(
1250+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1251+ );
11951252
11961253 const added = yield* executor.openapi.addSpec({
11971254 spec: { kind: "blob", value: microsoftGraphScaleSpecText() },
@@ -1208,7 +1265,9 @@ paths: · 10 unmodified lines
12081265 Effect.scoped(
12091266 Effect.gen(function* () {
12101267 const server = yield* servePluginTestApi();
1211− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1268+ const executor = yield* createExecutor(
1269+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1270+ );
12121271
12131272 yield* addOpenApiTestConnection(executor, server, { slug: "removable" });
12141273 expect((yield* executor.tools.list()).map((t) => String(t.name))).toContain(
@@ -1232,7 +1291,9 @@ paths: · 17 unmodified lines
12321291 Effect.scoped(
12331292 Effect.gen(function* () {
12341293 const server = yield* servePluginTestApi();
1235− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1294+ const executor = yield* createExecutor(
1295+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1296+ );
12361297
12371298 // First add carries an apiKey auth template + a distinctive description.
12381299 // A silent upsert on re-add would clobber both.
@@ -1294,7 +1355,9 @@ paths: · 55 unmodified lines
12941355 // The mutable spec server is a real 127.0.0.1 listener — reach it over
12951356 // the default fetch-based client, like production would.
12961357 const specServer = yield* serveMutableOpenApiSpecTestServer({ initialApi: TestApi });
1297− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1358+ const executor = yield* createExecutor(
1359+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1360+ );
12981361
12991362 const added = yield* executor.openapi.addSpec({
13001363 spec: { kind: "url", url: specServer.specUrl },
@@ -1370,7 +1433,7 @@ paths: · 69 unmodified lines
13701433 it.effect("denies member updateSpec before writing an org blob", () =>
13711434 Effect.gen(function* () {
13721435 const blobs = recordingBlobStore();
1373− const config = makeTestConfig({ plugins: testPlugins() });
1436+ const config = makeTestConfig({ access: testAccess.member(), plugins: testPlugins() });
13741437 const admin = yield* createExecutor({ ...config, blobs: blobs.store });
13751438 yield* admin.openapi.addSpec({
13761439 spec: { kind: "blob", value: testApiSpecText() },
@@ -1380,7 +1443,7 @@ paths: · 3 unmodified lines
13801443 const member = yield* createExecutor({
13811444 ...config,
13821445 blobs: blobs.store,
1383− orgWrites: "denied",
1446+ access: testAccess.member("denied"),
13841447 });
13851448
13861449 const error = yield* member.openapi
@@ -1398,7 +1461,9 @@ paths: · 11 unmodified lines
13981461 Effect.scoped(
13991462 Effect.gen(function* () {
14001463 const server = yield* servePluginTestApi();
1401− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1464+ const executor = yield* createExecutor(
1465+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1466+ );
14021467 yield* addOpenApiTestConnection(executor, server, { slug: "pasted" });
14031468
14041469 // A pasted-blob integration has no source URL — re-fetch must say so.
@@ -1450,6 +1515,7 @@ paths: · 45 unmodified lines
14501515 const plugins = testPlugins();
14511516
14521517 const alice = yield* makeTestWorkspaceHarness({
1518+ access: testAccess.member(),
14531519 plugins,
14541520 tenant,
14551521 subject: "alice",
@@ -1470,6 +1536,7 @@ paths: · 14 unmodified lines
14701536 });
14711537
14721538 const bob = yield* makeTestWorkspaceHarness({
1539+ access: testAccess.member(),
14731540 plugins,
14741541 tenant,
14751542 subject: "bob",
@@ -1513,7 +1580,9 @@ paths: · 37 unmodified lines
15131580
15141581 it.effect("updateSpec on an unknown slug fails with IntegrationNotFoundError", () =>
15151582 Effect.gen(function* () {
1516− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
1583+ const executor = yield* createExecutor(
1584+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
1585+ );
15171586 const error = yield* executor.openapi.updateSpec("missing").pipe(Effect.flip);
15181587 expect(Predicate.isTagged(error, "IntegrationNotFoundError")).toBe(true);
15191588 }),
packages/plugins/openapi/src/sdk/real-specs.test.ts+2−0
@@ -28,6 +28,7 @@ import { openApiPlugin } from "./plugin"; · 27 unmodified lines
2828 import { deriveAuthenticationTemplateFromPreview } from "./derive-auth";
2929 import { previewSpec as previewSpecRaw } from "./preview";
3030 import type { ExtractionResult } from "./types";
31+import { testAccess } from "@executor-js/product-access/testing";
3132
3233 const previewSpec = (input: string) =>
3334 previewSpecRaw(input).pipe(Effect.provide(FetchHttpClient.layer));
@@ -91,6 +92,7 @@ const getRegisteredToolSchema = (slug: string, specText: string, toolName: strin · 57 unmodified lines
9192
9293 const executor = yield* createExecutor(
9394 makeTestConfig({
95+ access: testAccess.member(),
9496 plugins: [openApiPlugin(), memoryCredentialsPlugin()] as const,
9597 }),
9698 );
packages/plugins/openapi/src/sdk/response-body-timeout.test.ts+4−1
@@ -16,6 +16,7 @@ import { makeTestConfig, memoryCredentialsPlugin } from "@executor-js/sdk/testin · 15 unmodified lines
1616 import { makeOpenApiHttpApiTestIntegrationConfig } from "../testing";
1717
1818 import { openApiPlugin } from "./plugin";
19+import { testAccess } from "@executor-js/product-access/testing";
1920
2021 const BODY_READ_DEADLINE_MS = 15_000;
2122 const RESPONSE_BODY_TIMEOUT_MS = 100;
@@ -42,7 +43,9 @@ const testPlugins = () => · 20 unmodified lines
4243
4344 const buildExecutor = (baseUrl: string) =>
4445 Effect.gen(function* () {
45− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
46+ const executor = yield* createExecutor(
47+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
48+ );
4649 yield* executor.openapi.addSpec(
4750 makeOpenApiHttpApiTestIntegrationConfig(TimeoutApi, {
4851 slug: "body_timeout",
packages/plugins/openapi/src/sdk/response-headers-timeout.test.ts+4−1
@@ -18,6 +18,7 @@ import { makeOpenApiHttpApiTestIntegrationConfig, unwrapInvocation } from "../te · 17 unmodified lines
1818 import { invokeWithLayer } from "./invoke";
1919 import { openApiPlugin } from "./plugin";
2020 import type { OperationBinding } from "./types";
21+import { testAccess } from "@executor-js/product-access/testing";
2122
2223 const RESPONSE_HEADERS_TIMEOUT_MS = 100;
2324 const STREAM_TOOL = "logs.getLogs";
@@ -44,7 +45,9 @@ const testPlugins = () => · 20 unmodified lines
4445
4546 const buildExecutor = (baseUrl: string) =>
4647 Effect.gen(function* () {
47− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
48+ const executor = yield* createExecutor(
49+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
50+ );
4851 yield* executor.openapi.addSpec(
4952 makeOpenApiHttpApiTestIntegrationConfig(TimeoutApi, { slug: "headers_timeout", baseUrl }),
5053 );
packages/plugins/openapi/src/sdk/spec-blob.test.ts+15−6
@@ -38,6 +38,7 @@ import { · 37 unmodified lines
3838 serveOpenApiHttpApiTestServer,
3939 unwrapInvocation,
4040 } from "../testing";
41+import { testAccess } from "@executor-js/product-access/testing";
4142
4243 const testPlugins = (httpClientLayer = FetchHttpClient.layer) =>
4344 [openApiPlugin({ httpClientLayer }), memoryCredentialsPlugin()] as const;
@@ -113,7 +114,9 @@ describe("OpenAPI plugin — spec blob storage", () => { · 69 unmodified lines
113114 it.effect("addSpec stores a content pointer, not the inline spec text", () =>
114115 Effect.scoped(
115116 Effect.gen(function* () {
116− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
117+ const executor = yield* createExecutor(
118+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
119+ );
117120 const text = specText();
118121
119122 yield* executor.openapi.addSpec({
@@ -135,7 +138,9 @@ describe("OpenAPI plugin — spec blob storage", () => { · 15 unmodified lines
135138 api: TestApi,
136139 handlersLayer: EchoGroupLive,
137140 });
138− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
141+ const executor = yield* createExecutor(
142+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
143+ );
139144
140145 yield* executor.openapi.addSpec({
141146 spec: { kind: "blob", value: server.specJson },
@@ -168,7 +173,7 @@ describe("OpenAPI plugin — spec blob storage", () => { · 26 unmodified lines
168173 () =>
169174 Effect.scoped(
170175 Effect.gen(function* () {
171− const config = makeTestConfig({ plugins: testPlugins() });
176+ const config = makeTestConfig({ access: testAccess.member(), plugins: testPlugins() });
172177 const executor = yield* createExecutor(config);
173178 const text = specTextWithDefinition();
174179 const hash = yield* sha256Hex(text);
@@ -245,7 +250,7 @@ describe("OpenAPI plugin — spec blob storage", () => { · 70 unmodified lines
245250 it.effect("stale sync preserves tools and definitions when the spec blob is missing", () =>
246251 Effect.scoped(
247252 Effect.gen(function* () {
248− const config = makeTestConfig({ plugins: testPlugins() });
253+ const config = makeTestConfig({ access: testAccess.member(), plugins: testPlugins() });
249254 const executor = yield* createExecutor(config);
250255 const text = specTextWithDefinition();
251256 const hash = yield* sha256Hex(text);
@@ -318,7 +323,9 @@ describe("OpenAPI plugin — spec blob storage", () => { · 66 unmodified lines
318323 it.effect("explicit spec refresh accepts a valid OpenAPI document with zero operations", () =>
319324 Effect.scoped(
320325 Effect.gen(function* () {
321− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
326+ const executor = yield* createExecutor(
327+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
328+ );
322329 const emptySpec = JSON.stringify({
323330 openapi: "3.1.0",
324331 info: { title: "Empty", version: "1.0.0" },
@@ -409,7 +416,9 @@ describe("OpenAPI plugin — spec blob storage", () => { · 84 unmodified lines
409416 it.effect("remove + re-add of the same spec is idempotent over the shared blob", () =>
410417 Effect.scoped(
411418 Effect.gen(function* () {
412− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
419+ const executor = yield* createExecutor(
420+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
421+ );
413422 const text = specText();
414423
415424 yield* executor.openapi.addSpec({ spec: { kind: "blob", value: text }, slug: "re_add" });
packages/plugins/openapi/src/sdk/spec-overrides-lifecycle.test.ts+10−3
@@ -9,6 +9,7 @@ import { makeTestConfig, memoryCredentialsPlugin } from "@executor-js/sdk/testin · 8 unmodified lines
99 import { openApiPlugin } from "./plugin";
1010 import { applySpecOverrides, type SpecOverrides } from "./spec-overrides";
1111 import { serveMutableOpenApiSpecTestServer } from "../testing";
12+import { testAccess } from "@executor-js/product-access/testing";
1213
1314 const testPlugins = () =>
1415 [openApiPlugin({ httpClientLayer: FetchHttpClient.layer }), memoryCredentialsPlugin()] as const;
@@ -60,7 +61,9 @@ describe("OpenAPI spec override lifecycle", () => { · 45 unmodified lines
6061 it.effect("applies scope overrides to preview and persists raw and patched hashes", () =>
6162 Effect.scoped(
6263 Effect.gen(function* () {
63− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
64+ const executor = yield* createExecutor(
65+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
66+ );
6467 const sourceText = encodeJsonText(oauthSpec);
6568
6669 const preview = yield* executor.openapi.previewSpec({
@@ -93,7 +96,9 @@ describe("OpenAPI spec override lifecycle", () => { · 26 unmodified lines
9396 it.effect("changes and clears overrides for an inline spec without repasting the source", () =>
9497 Effect.scoped(
9598 Effect.gen(function* () {
96− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
99+ const executor = yield* createExecutor(
100+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
101+ );
97102 const sourceText = encodeJsonText(oauthSpec);
98103 yield* executor.openapi.addSpec({
99104 spec: { kind: "blob", value: sourceText },
@@ -130,7 +135,9 @@ describe("OpenAPI spec override lifecycle", () => { · 30 unmodified lines
130135 .add(HttpApiEndpoint.post("create", "/items", { success: Schema.String }));
131136 const InitialApi = HttpApi.make("initial").add(Items);
132137 const server = yield* serveMutableOpenApiSpecTestServer({ initialApi: InitialApi });
133− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
138+ const executor = yield* createExecutor(
139+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
140+ );
134141 const removeList: SpecOverrides = [{ op: "remove", path: "/paths/~1items/get" }];
135142
136143 yield* executor.openapi.addSpec({
packages/plugins/openapi/src/sdk/streaming-response.test.ts+7−2
@@ -17,6 +17,7 @@ import { makeOpenApiHttpApiTestIntegrationConfig, unwrapInvocation } from "../te · 16 unmodified lines
1717
1818 import { collectStreamingBody, STREAM_MAX_BYTES } from "./invoke";
1919 import { openApiPlugin } from "./plugin";
20+import { testAccess } from "@executor-js/product-access/testing";
2021
2122 const testPlugins = () =>
2223 [openApiPlugin({ httpClientLayer: FetchHttpClient.layer }), memoryCredentialsPlugin()] as const;
@@ -35,7 +36,9 @@ const StreamingApi = HttpApi.make("streamingResponseTest") · 12 unmodified lines
3536
3637 const buildExecutor = (baseUrl: string) =>
3738 Effect.gen(function* () {
38− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
39+ const executor = yield* createExecutor(
40+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
41+ );
3942 yield* executor.openapi.addSpec(
4043 makeOpenApiHttpApiTestIntegrationConfig(StreamingApi, { slug: "streaming", baseUrl }),
4144 );
@@ -293,7 +296,9 @@ describe("OpenAPI streaming responses", () => { · 251 unmodified lines
293296 );
294297 });
295298
296− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
299+ const executor = yield* createExecutor(
300+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
301+ );
297302 yield* executor.openapi.addSpec({
298303 spec: {
299304 kind: "blob",
packages/plugins/openapi/src/sdk/tool-row-projection.test.ts+4−1
@@ -25,6 +25,7 @@ import { variable } from "@executor-js/sdk/http-auth"; · 24 unmodified lines
2525
2626 import { openApiPlugin } from "./plugin";
2727 import { serveOpenApiHttpApiTestServer, unwrapInvocation } from "../testing";
28+import { testAccess } from "@executor-js/product-access/testing";
2829
2930 const testPlugins = (httpClientLayer = FetchHttpClient.layer) =>
3031 [openApiPlugin({ httpClientLayer }), memoryCredentialsPlugin()] as const;
@@ -58,7 +59,9 @@ const setup = Effect.gen(function* () { · 27 unmodified lines
5859 api: TestApi,
5960 handlersLayer: EchoGroupLive,
6061 });
61− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
62+ const executor = yield* createExecutor(
63+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
64+ );
6265 yield* executor.openapi.addSpec({
6366 spec: { kind: "blob", value: server.specJson },
6467 slug: "proj_api",
packages/plugins/openapi/src/sdk/upstream-failures.test.ts+8−3
@@ -48,6 +48,7 @@ import { · 47 unmodified lines
4848 } from "../testing";
4949
5050 import { openApiPlugin } from "./plugin";
51+import { testAccess } from "@executor-js/product-access/testing";
5152
5253 class AdapterDefect extends Data.TaggedError("AdapterDefect") {}
5354
@@ -149,7 +150,7 @@ const FailureApi = HttpApi.make("failuresTest") · 95 unmodified lines
149150 const buildExecutor = (baseUrl: string, httpClientLayer = FetchHttpClient.layer) =>
150151 Effect.gen(function* () {
151152 const executor = yield* createExecutor(
152− makeTestConfig({ plugins: testPlugins(httpClientLayer) }),
153+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins(httpClientLayer) }),
153154 );
154155 yield* executor.openapi.addSpec(
155156 makeOpenApiHttpApiTestIntegrationConfig(FailureApi, { slug: "f", baseUrl }),
@@ -167,7 +168,9 @@ const buildExecutor = (baseUrl: string, httpClientLayer = FetchHttpClient.layer) · 11 unmodified lines
167168
168169 const buildExecutorForOpenApiServer = (server: OpenApiTestServerShape) =>
169170 Effect.gen(function* () {
170− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
171+ const executor = yield* createExecutor(
172+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
173+ );
171174 const conn = yield* addOpenApiTestConnection(executor, server, { slug: "f" });
172175 return { executor, address: conn.address(LIST_THINGS) };
173176 });
@@ -349,7 +352,9 @@ describe("OpenAPI upstream failure modes", () => { · 175 unmodified lines
349352 headers: { "content-type": "application/json" },
350353 body: '{"error":{"status":"PERMISSION_DENIED","details":[{"reason":"ACCESS_TOKEN_SCOPE_INSUFFICIENT"}]}}',
351354 }));
352− const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
355+ const executor = yield* createExecutor(
356+ makeTestConfig({ access: testAccess.member(), plugins: testPlugins() }),
357+ );
353358 // Declare the operation's scope in the spec blob before registering it,
354359 // so the extracted binding carries requiredScopes.
355360 const SpecJson = Schema.fromJsonString(Schema.Record(Schema.String, Schema.Unknown));