@executor-js/sdk 1.5.6 → 1.5.7

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 (67) hide show
  1. package/dist/blob.d.ts +4 -0
  2. package/dist/blob.d.ts.map +1 -1
  3. package/dist/{chunk-VAJYYP2A.js → chunk-ARH4MAGG.js} +2 -2
  4. package/dist/{chunk-777N6JVG.js → chunk-I3X6242Q.js} +1 -1
  5. package/dist/chunk-I3X6242Q.js.map +1 -0
  6. package/dist/{chunk-3RRMGXEN.js → chunk-UKOTOKXM.js} +1 -1
  7. package/dist/{chunk-3RRMGXEN.js.map → chunk-UKOTOKXM.js.map} +1 -1
  8. package/dist/{chunk-WN6EB76P.js → chunk-YPVKRUZV.js} +50 -16
  9. package/dist/chunk-YPVKRUZV.js.map +1 -0
  10. package/dist/core-schema.d.ts +7 -0
  11. package/dist/core-schema.d.ts.map +1 -1
  12. package/dist/core.js +175 -9
  13. package/dist/core.js.map +1 -1
  14. package/dist/executor-fuma-db.d.ts +8 -0
  15. package/dist/executor-fuma-db.d.ts.map +1 -1
  16. package/dist/executor.d.ts +8 -0
  17. package/dist/executor.d.ts.map +1 -1
  18. package/dist/host-internal.js +3 -3
  19. package/dist/http-auth/auth-method.d.ts +81 -0
  20. package/dist/http-auth/auth-method.d.ts.map +1 -0
  21. package/dist/http-auth/auth-method.test.d.ts +2 -0
  22. package/dist/http-auth/auth-method.test.d.ts.map +1 -0
  23. package/dist/http-auth/authoring.d.ts +52 -0
  24. package/dist/http-auth/authoring.d.ts.map +1 -0
  25. package/dist/http-auth/authoring.test.d.ts +2 -0
  26. package/dist/http-auth/authoring.test.d.ts.map +1 -0
  27. package/dist/http-auth/index.d.ts +5 -0
  28. package/dist/http-auth/index.d.ts.map +1 -0
  29. package/dist/http-auth/legacy.d.ts +42 -0
  30. package/dist/http-auth/legacy.d.ts.map +1 -0
  31. package/dist/http-auth/migrate.d.ts +30 -0
  32. package/dist/http-auth/migrate.d.ts.map +1 -0
  33. package/dist/http-auth/migrate.test.d.ts +2 -0
  34. package/dist/http-auth/migrate.test.d.ts.map +1 -0
  35. package/dist/http-auth.js +288 -0
  36. package/dist/http-auth.js.map +1 -0
  37. package/dist/index.d.ts +7 -4
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +2 -4
  40. package/dist/index.js.map +1 -1
  41. package/dist/integration.d.ts +8 -0
  42. package/dist/integration.d.ts.map +1 -1
  43. package/dist/oauth-client.d.ts +3 -2
  44. package/dist/oauth-client.d.ts.map +1 -1
  45. package/dist/plugin.d.ts +18 -5
  46. package/dist/plugin.d.ts.map +1 -1
  47. package/dist/promise.d.ts +1 -1
  48. package/dist/promise.d.ts.map +1 -1
  49. package/dist/shared.js +1 -1
  50. package/dist/sqlite-config-blob-migration.d.ts +23 -0
  51. package/dist/sqlite-config-blob-migration.d.ts.map +1 -0
  52. package/dist/sqlite-config-blob-migration.test.d.ts +2 -0
  53. package/dist/sqlite-config-blob-migration.test.d.ts.map +1 -0
  54. package/dist/sqlite-data-migrations.d.ts +50 -0
  55. package/dist/sqlite-data-migrations.d.ts.map +1 -0
  56. package/dist/sqlite-data-migrations.test.d.ts +2 -0
  57. package/dist/sqlite-data-migrations.test.d.ts.map +1 -0
  58. package/dist/sqlite-test-db-KBW52UM6.js +9 -0
  59. package/dist/testing.js +7 -7
  60. package/dist/tool-result.d.ts +15 -1
  61. package/dist/tool-result.d.ts.map +1 -1
  62. package/package.json +8 -2
  63. package/dist/chunk-777N6JVG.js.map +0 -1
  64. package/dist/chunk-WN6EB76P.js.map +0 -1
  65. package/dist/sqlite-test-db-AMRR6VZ6.js +0 -9
  66. /package/dist/{chunk-VAJYYP2A.js.map → chunk-ARH4MAGG.js.map} +0 -0
  67. /package/dist/{sqlite-test-db-AMRR6VZ6.js.map → sqlite-test-db-KBW52UM6.js.map} +0 -0
package/dist/blob.d.ts CHANGED
@@ -52,5 +52,9 @@ export declare const pluginBlobStore: (store: BlobStore, partitions: OwnerPartit
52
52
  * `BlobStore` interface.
53
53
  */
54
54
  export declare const makeInMemoryBlobStore: () => BlobStore;
55
+ /** Hex SHA-256 of a UTF-8 string — the content-address key plugins use for
56
+ * write-once blobs (`put(key(hash), …)` is then idempotent and orphaned
57
+ * writes are harmless). Web Crypto, so it runs on Workers/Bun/Node alike. */
58
+ export declare const sha256Hex: (text: string) => Effect.Effect<string>;
55
59
  export declare const makeFumaBlobStore: (fuma: IFumaClient) => BlobStore;
56
60
  //# sourceMappingURL=blob.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"blob.d.ts","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAEnC,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC;IAC7F;;;;4BAIwB;IACxB,QAAQ,CAAC,OAAO,EAAE,CAChB,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,GAAG,EAAE,MAAM,KACR,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC;IAC9D,QAAQ,CAAC,GAAG,EAAE,CACZ,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,KACV,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACvF,QAAQ,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;CACxF;AAED,MAAM,WAAW,eAAe;IAC9B;wDACoD;IACpD,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC;IAC1E;6EACyE;IACzE,QAAQ,CAAC,GAAG,EAAE,CACZ,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;KAAE,KAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACvC,wCAAwC;IACxC,QAAQ,CAAC,MAAM,EAAE,CACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;KAAE,KAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACvC,sEAAsE;IACtE,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;CACrE;AAED;;uEAEuE;AACvE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAID;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,SAAS,EAChB,YAAY,eAAe,EAC3B,UAAU,MAAM,KACf,eAyCF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,QAAO,SAwBxC,CAAC;AAaF,eAAO,MAAM,iBAAiB,GAAI,MAAM,WAAW,KAAG,SA2EpD,CAAC"}
1
+ {"version":3,"file":"blob.d.ts","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAEnC,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC;IAC7F;;;;4BAIwB;IACxB,QAAQ,CAAC,OAAO,EAAE,CAChB,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,GAAG,EAAE,MAAM,KACR,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC;IAC9D,QAAQ,CAAC,GAAG,EAAE,CACZ,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,KACV,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACvF,QAAQ,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;CACxF;AAED,MAAM,WAAW,eAAe;IAC9B;wDACoD;IACpD,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC;IAC1E;6EACyE;IACzE,QAAQ,CAAC,GAAG,EAAE,CACZ,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;KAAE,KAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACvC,wCAAwC;IACxC,QAAQ,CAAC,MAAM,EAAE,CACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;KAAE,KAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACvC,sEAAsE;IACtE,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;CACrE;AAED;;uEAEuE;AACvE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAID;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,SAAS,EAChB,YAAY,eAAe,EAC3B,UAAU,MAAM,KACf,eAyCF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,QAAO,SAwBxC,CAAC;AAEF;;8EAE8E;AAC9E,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAMzD,CAAC;AAaL,eAAO,MAAM,iBAAiB,GAAI,MAAM,WAAW,KAAG,SA2EpD,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createExecutorFumaDb
3
- } from "./chunk-777N6JVG.js";
3
+ } from "./chunk-I3X6242Q.js";
4
4
  import {
5
5
  __commonJS,
6
6
  __require,
@@ -14745,4 +14745,4 @@ var createSqliteTestFumaDb = async (options) => {
14745
14745
  export {
14746
14746
  createSqliteTestFumaDb
14747
14747
  };
14748
- //# sourceMappingURL=chunk-VAJYYP2A.js.map
14748
+ //# sourceMappingURL=chunk-ARH4MAGG.js.map
@@ -28,4 +28,4 @@ var createExecutorFumaDb = (drizzleDb, options) => {
28
28
  export {
29
29
  createExecutorFumaDb
30
30
  };
31
- //# sourceMappingURL=chunk-777N6JVG.js.map
31
+ //# sourceMappingURL=chunk-I3X6242Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/executor-fuma-db.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Shared FumaDB assembly (pure, driver-agnostic).\n//\n// Every host (self-host, local, sdk-test, cloud) historically hand-rolled the\n// same driver-agnostic FumaDB wiring: build a fumadb factory from the latest\n// schema, bind it to an already-opened drizzle handle through `drizzleAdapter`,\n// and expose `{ db: fuma.orm(version), fuma }`. `createExecutorFumaDb` owns ONLY\n// that assembly — the caller still opens its own driver (libSQL for SQLite,\n// postgres-js for Postgres), applies its own PRAGMAs, and runs its own schema\n// bring-up. The factory is dialect-generic via the `provider` param.\n//\n// This is a pure helper, not the `DbProvider` Effect seam. The seam\n// (`DbProvider` / `dbProviderLayer`) is host-composition and lives in the host\n// layer (`@executor-js/api/server`). This assembly stays in the SDK because the\n// SDK's own sqlite test backend (`sqlite-test-db.ts`) builds its handle with it;\n// hosts reach it (and the seam) through `@executor-js/api/server`, which\n// re-exports `createExecutorFumaDb` from here. It is NOT on the plugin-author\n// root barrel — host code imports it from `@executor-js/sdk/host-internal`.\n// ---------------------------------------------------------------------------\n\nimport { fumadb, type FumaDB } from \"@executor-js/fumadb\";\nimport { type DrizzleRuntimeProvider } from \"@executor-js/fumadb/adapters/drizzle\";\nimport { drizzleAdapter } from \"@executor-js/fumadb/adapters/drizzle\";\nimport { schema as fumaSchema, type RelationsMap } from \"@executor-js/fumadb/schema\";\n\nimport type { BlobStore } from \"./blob\";\nimport type { FumaDb, FumaTables } from \"./fuma-runtime\";\n\n// The FumaDB provider both the runtime-schema generator and the drizzle adapter\n// understand. SQLite (libSQL) and PostgreSQL (postgres-js) are the only\n// dialects in use today.\nexport type ExecutorDbProvider = DrizzleRuntimeProvider;\n\nexport type ExecutorFumaSchema<TTables extends FumaTables> = ReturnType<\n typeof fumaSchema<string, TTables, RelationsMap<TTables>>\n>;\n\nexport interface ExecutorFumaDb<TTables extends FumaTables = FumaTables> {\n readonly db: FumaDb<ExecutorFumaSchema<TTables>>;\n readonly fuma: FumaDB<ExecutorFumaSchema<TTables>[]>;\n}\n\nexport interface CreateExecutorFumaDbOptions<TTables extends FumaTables = FumaTables> {\n readonly tables: TTables;\n readonly namespace: string;\n readonly version: string;\n readonly provider: ExecutorDbProvider;\n /**\n * Whether the engine supports interactive transactions (BEGIN/COMMIT).\n * Defaults to `true`. Cloudflare D1 must pass `false` — it rejects\n * interactive transactions, so the adapter runs transaction callbacks\n * directly (auto-commit per statement). libSQL/Postgres keep real\n * transactions.\n */\n readonly interactiveTransactions?: boolean;\n /**\n * Maximum bound parameters per query (Cloudflare D1: 100). When set,\n * `createMany` batches so `rows * columns` stays within it. Unset for\n * libSQL/Postgres (no tight cap).\n */\n readonly maxBoundParameters?: number;\n}\n\n/**\n * Driver-agnostic FumaDB assembly. The caller passes an already-opened drizzle\n * handle (it owns the driver, PRAGMAs, and schema bring-up); this wires the\n * fumadb client over it and returns the `{ db, fuma }` query surface.\n *\n * NOTE: the drizzle `db` must already have its runtime schema attached (via\n * `createDrizzleRuntimeSchemaFromTables`) for SQLite/Postgres relational\n * queries to resolve — that schema generation stays caller-side because it is\n * coupled to the caller's drizzle() construction.\n */\nexport const createExecutorFumaDb = <const TTables extends FumaTables>(\n drizzleDb: unknown,\n options: CreateExecutorFumaDbOptions<TTables>,\n): ExecutorFumaDb<TTables> => {\n const latestSchema = fumaSchema({\n version: options.version,\n tables: options.tables,\n });\n const factory = fumadb({\n namespace: options.namespace,\n schemas: [latestSchema],\n });\n const fuma = factory.client(\n drizzleAdapter({\n db: drizzleDb,\n provider: options.provider,\n interactiveTransactions: options.interactiveTransactions,\n maxBoundParameters: options.maxBoundParameters,\n }),\n );\n\n return {\n db: fuma.orm(options.version),\n fuma,\n };\n};\n\n// The uniform handle each host exposes through the `DbProvider` Layer (defined\n// in the host layer). The `db`/`fuma` come from `createExecutorFumaDb`; `close`\n// releases the host's own driver. Hosts that keep extra connection objects (the\n// raw sqlite handle, the postgres `sql`) layer those into their own concrete\n// handle type and still satisfy this contract.\nexport interface ExecutorDbHandle<\n TTables extends FumaTables = FumaTables,\n> extends ExecutorFumaDb<TTables> {\n readonly close: () => Promise<void>;\n /**\n * Optional blob backend assembled alongside the driver (an R2 bucket on the\n * Cloudflare hosts). `makeScopedExecutor` threads it into\n * `createExecutor({ blobs })`; absent, the executor defaults to the FumaDB\n * `blob` table over `db`.\n */\n readonly blobs?: BlobStore;\n}\n"],"mappings":";AAoBA,SAAS,cAA2B;AAEpC,SAAS,sBAAsB;AAC/B,SAAS,UAAU,kBAAqC;AAkDjD,IAAM,uBAAuB,CAClC,WACA,YAC4B;AAC5B,QAAM,eAAe,WAAW;AAAA,IAC9B,SAAS,QAAQ;AAAA,IACjB,QAAQ,QAAQ;AAAA,EAClB,CAAC;AACD,QAAM,UAAU,OAAO;AAAA,IACrB,WAAW,QAAQ;AAAA,IACnB,SAAS,CAAC,YAAY;AAAA,EACxB,CAAC;AACD,QAAM,OAAO,QAAQ;AAAA,IACnB,eAAe;AAAA,MACb,IAAI;AAAA,MACJ,UAAU,QAAQ;AAAA,MAClB,yBAAyB,QAAQ;AAAA,MACjC,oBAAoB,QAAQ;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,IAAI,KAAK,IAAI,QAAQ,OAAO;AAAA,IAC5B;AAAA,EACF;AACF;","names":[]}
@@ -335,4 +335,4 @@ export {
335
335
  ToolSchemaView,
336
336
  IntegrationDetectionResult
337
337
  };
338
- //# sourceMappingURL=chunk-3RRMGXEN.js.map
338
+ //# sourceMappingURL=chunk-UKOTOKXM.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/policies.ts","../src/elicitation.ts","../src/errors.ts","../src/oauth-client.ts","../src/types.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Tool policies — pattern matcher + policy resolution. Pure functions; the\n// executor stitches them into `tools.list`, `execute`, and the public\n// `executor.policies` CRUD surface. Plugins consume the same surface.\n//\n// v2: policies are owner-scoped (org | user) instead of scope-stacked. Each\n// owner contributes its first matching rule by local position; the final answer\n// is the most restrictive matched action across owners, so a user preference\n// cannot weaken an org guardrail (org = outer, user = inner).\n// ---------------------------------------------------------------------------\n\nimport { Match, Schema } from \"effect\";\n\nimport type { ToolPolicyAction, ToolPolicyRow } from \"./core-schema\";\nimport { Owner, PolicyId } from \"./ids\";\n\nexport interface ToolPolicy {\n readonly id: PolicyId;\n readonly owner: Owner;\n readonly pattern: string;\n readonly action: ToolPolicyAction;\n /** Fractional-indexing key. Lower lex order = higher precedence. */\n readonly position: string;\n readonly createdAt: Date;\n readonly updatedAt: Date;\n}\n\nexport interface CreateToolPolicyInput {\n readonly owner: Owner;\n readonly pattern: string;\n /** Optional explicit position. Defaults to a key above the current minimum\n * (top of the owner's list; highest precedence). */\n readonly action: ToolPolicyAction;\n readonly position?: string;\n}\n\nexport interface UpdateToolPolicyInput {\n readonly id: string;\n readonly owner: Owner;\n readonly pattern?: string;\n readonly action?: ToolPolicyAction;\n readonly position?: string;\n}\n\nexport interface RemoveToolPolicyInput {\n readonly id: string;\n readonly owner: Owner;\n}\n\n// ---------------------------------------------------------------------------\n// Match result.\n// ---------------------------------------------------------------------------\n\nexport interface PolicyMatch {\n readonly action: ToolPolicyAction;\n readonly pattern: string;\n readonly policyId: string;\n}\n\nexport type PolicySource = \"user\" | \"plugin-default\";\n\nexport interface EffectivePolicy {\n readonly action: ToolPolicyAction;\n readonly source: PolicySource;\n readonly pattern?: string;\n readonly policyId?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Pattern matching. Grammar (matched against the full tool address\n// `<integration>.<owner>.<connection>.<tool>` or a shorter form the executor\n// passes in):\n// - universal: `*`\n// - exact: `vercel.dns.create`\n// - subtree (trailing `*`): `vercel.dns.*` — the literal prefix plus anything deeper\n// - plugin-wide: `vercel.*`\n// - mid-segment `*`: `vercel.*.*.dns.create` — each NON-trailing `*` matches\n// EXACTLY ONE segment (e.g. wildcard the owner/connection\n// segments to target a tool across every connection).\n// A `*` is always a complete segment: mid-pattern it consumes one segment,\n// trailing it is a subtree. Partial wildcards (`me*`) and a leading `*` (other\n// than the universal `*`) are rejected by `isValidPattern`.\n// ---------------------------------------------------------------------------\n\nexport const matchPattern = (pattern: string, toolId: string): boolean => {\n if (pattern === \"*\") return true;\n const patternSegments = pattern.split(\".\");\n const toolSegments = toolId.split(\".\");\n for (let i = 0; i < patternSegments.length; i++) {\n const seg = patternSegments[i]!;\n if (seg === \"*\") {\n // Trailing `*` is a subtree: the literal prefix already matched, so the\n // address matches at this position and anything deeper (or nothing).\n if (i === patternSegments.length - 1) return toolSegments.length >= i;\n // A non-trailing `*` consumes EXACTLY ONE segment; one must exist here.\n if (i >= toolSegments.length) return false;\n continue;\n }\n if (i >= toolSegments.length || toolSegments[i] !== seg) return false;\n }\n // Pattern exhausted with no trailing `*`: an exact match requires equal length.\n return patternSegments.length === toolSegments.length;\n};\n\nexport const isValidPattern = (pattern: string): boolean => {\n if (pattern.length === 0) return false;\n if (pattern === \"*\") return true;\n if (pattern.startsWith(\".\") || pattern.endsWith(\".\")) return false;\n if (pattern.includes(\"..\")) return false;\n if (pattern.startsWith(\"*\")) return false;\n const segments = pattern.split(\".\");\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i]!;\n if (seg.length === 0) return false;\n // A `*` segment must be the WHOLE segment — no partial wildcards (`me*`).\n // A `*` is valid mid-pattern (one segment) or trailing (subtree).\n if (seg.includes(\"*\") && seg !== \"*\") return false;\n }\n return true;\n};\n\n// ---------------------------------------------------------------------------\n// Resolution — each owner contributes its first matching rule by local\n// position; the most restrictive matched action across owners wins. Caller\n// passes an `ownerRank` so the resolver doesn't need to know which owner is\n// the outer guardrail.\n// ---------------------------------------------------------------------------\n\nexport const comparePolicyRow = (\n a: Pick<ToolPolicyRow, \"position\" | \"id\">,\n b: Pick<ToolPolicyRow, \"position\" | \"id\">,\n): number => {\n const pa = a.position;\n const pb = b.position;\n if (pa < pb) return -1;\n if (pa > pb) return 1;\n const ia = a.id;\n const ib = b.id;\n return ia < ib ? -1 : ia > ib ? 1 : 0;\n};\n\nconst actionRestrictionRank = (action: ToolPolicyAction): number =>\n Match.value(action).pipe(\n Match.when(\"block\", () => 3),\n Match.when(\"require_approval\", () => 2),\n Match.when(\"approve\", () => 1),\n Match.exhaustive,\n );\n\nconst moreRestrictive = <T extends { readonly action: ToolPolicyAction }>(\n current: T | undefined,\n candidate: T,\n): T => {\n if (!current) return candidate;\n const currentRank = actionRestrictionRank(current.action);\n const candidateRank = actionRestrictionRank(candidate.action);\n return candidateRank > currentRank ? candidate : current;\n};\n\nexport const resolveToolPolicy = (\n toolId: string,\n policies: readonly ToolPolicyRow[],\n ownerRank: (row: Pick<ToolPolicyRow, \"owner\">) => number,\n): PolicyMatch | undefined => {\n if (policies.length === 0) return undefined;\n const sorted = [...policies].sort((a, b) => {\n const sa = ownerRank(a);\n const sb = ownerRank(b);\n if (sa !== sb) return sa - sb;\n return comparePolicyRow(a, b);\n });\n const firstMatchByOwner = new Map<string, PolicyMatch>();\n for (const row of sorted) {\n if (firstMatchByOwner.has(row.owner)) continue;\n if (matchPattern(row.pattern, toolId)) {\n firstMatchByOwner.set(row.owner, {\n action: row.action as ToolPolicyAction,\n pattern: row.pattern,\n policyId: row.id,\n });\n }\n }\n let selected: PolicyMatch | undefined;\n for (const match of firstMatchByOwner.values()) {\n selected = moreRestrictive(selected, match);\n }\n return selected;\n};\n\n// ---------------------------------------------------------------------------\n// Layered resolution — user-authored rules + plugin default `requiresApproval`.\n// ---------------------------------------------------------------------------\n\nconst liftPlugin = (defaultRequiresApproval: boolean | undefined): EffectivePolicy =>\n defaultRequiresApproval\n ? { action: \"require_approval\", source: \"plugin-default\" }\n : { action: \"approve\", source: \"plugin-default\" };\n\nconst liftUser = (match: PolicyMatch): EffectivePolicy => ({\n action: match.action,\n source: \"user\",\n pattern: match.pattern,\n policyId: match.policyId,\n});\n\nexport const resolveEffectivePolicy = (\n toolId: string,\n policies: readonly ToolPolicyRow[],\n ownerRank: (row: Pick<ToolPolicyRow, \"owner\">) => number,\n defaultRequiresApproval?: boolean,\n): EffectivePolicy => {\n const match = resolveToolPolicy(toolId, policies, ownerRank);\n return match ? liftUser(match) : liftPlugin(defaultRequiresApproval);\n};\n\nexport const effectivePolicyFromSorted = (\n toolId: string,\n sortedPolicies: readonly (Pick<ToolPolicy, \"pattern\" | \"action\" | \"id\"> &\n Partial<Pick<ToolPolicy, \"owner\">>)[],\n defaultRequiresApproval?: boolean,\n): EffectivePolicy => {\n const firstMatchByOwner = new Map<string, EffectivePolicy>();\n for (const p of sortedPolicies) {\n const ownerKey = \"owner\" in p && p.owner ? String(p.owner) : \"__flat__\";\n if (firstMatchByOwner.has(ownerKey)) continue;\n if (matchPattern(p.pattern, toolId)) {\n firstMatchByOwner.set(ownerKey, {\n action: p.action,\n source: \"user\",\n pattern: p.pattern,\n policyId: p.id,\n });\n }\n }\n let selected: EffectivePolicy | undefined;\n for (const match of firstMatchByOwner.values()) {\n selected = moreRestrictive(selected, match);\n }\n return selected ?? liftPlugin(defaultRequiresApproval);\n};\n\n// ---------------------------------------------------------------------------\n// Row → public projection.\n// ---------------------------------------------------------------------------\n\nexport const rowToToolPolicy = (row: ToolPolicyRow): ToolPolicy => ({\n id: PolicyId.make(row.id),\n owner: row.owner as Owner,\n pattern: row.pattern,\n action: row.action as ToolPolicyAction,\n position: row.position,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n});\n\nexport const ToolPolicyActionSchema = Schema.Literals([\"approve\", \"require_approval\", \"block\"]);\n","import { Effect, Schema } from \"effect\";\n\nimport { ElicitationId, ToolAddress } from \"./ids\";\n\n/* A tool that needs user input mid-call suspends and the host's `onElicitation`\n * handler (executor-level, overridable per `execute`) answers. Tools that never\n * elicit never trigger it. Schema-tagged so requests/responses cross the wire. */\n\n/** Tool needs structured input from the user (render a form). */\nexport const FormElicitation = Schema.TaggedStruct(\"FormElicitation\", {\n message: Schema.String,\n /** JSON Schema describing the fields to collect. */\n requestedSchema: Schema.Record(Schema.String, Schema.Unknown),\n});\nexport type FormElicitation = typeof FormElicitation.Type;\n\n/** Tool needs the user to visit a URL (OAuth, approval page, etc.). */\nexport const UrlElicitation = Schema.TaggedStruct(\"UrlElicitation\", {\n message: Schema.String,\n url: Schema.String,\n /** Unique id so the host can correlate the callback. */\n elicitationId: ElicitationId,\n});\nexport type UrlElicitation = typeof UrlElicitation.Type;\n\nexport type ElicitationRequest = FormElicitation | UrlElicitation;\n\nexport const ElicitationAction = Schema.Literals([\"accept\", \"decline\", \"cancel\"]);\nexport type ElicitationAction = typeof ElicitationAction.Type;\n\nexport const ElicitationResponse = Schema.Struct({\n action: ElicitationAction,\n /** Present when `action` is \"accept\" — the data the user provided. */\n content: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n});\nexport type ElicitationResponse = typeof ElicitationResponse.Type;\n\n/** Handler input — the tool address being invoked, its args, and the request. */\nexport interface ElicitationContext {\n readonly address: ToolAddress;\n readonly args: unknown;\n readonly request: ElicitationRequest;\n}\n\n/** Host-provided handler the SDK calls when a tool suspends for input. */\nexport type ElicitationHandler = (ctx: ElicitationContext) => Effect.Effect<ElicitationResponse>;\n\n/** Executor-level elicitation policy: a handler, or `\"accept-all\"` to\n * auto-accept every request (tests / non-interactive hosts). */\nexport type OnElicitation = ElicitationHandler | \"accept-all\";\n\n/** Per-call options for `execute`. */\nexport interface InvokeOptions {\n /** Override the executor-level handler for this single call. */\n readonly onElicitation?: OnElicitation;\n}\n\n/** A tool was declined or cancelled during elicitation. */\nexport class ElicitationDeclinedError extends Schema.TaggedErrorClass<ElicitationDeclinedError>()(\n \"ElicitationDeclinedError\",\n {\n address: ToolAddress,\n action: Schema.Literals([\"decline\", \"cancel\"]),\n },\n) {}\n","import { Schema } from \"effect\";\n\nimport { ElicitationDeclinedError } from \"./elicitation\";\nimport type { StorageFailure } from \"./fuma-runtime\";\nimport { ConnectionName, IntegrationSlug, Owner, ProviderKey, ToolAddress } from \"./ids\";\n\n/* The failure set the SDK surfaces. `execute`'s invoke failures are ported from\n * v1 but re-keyed by `address` (the full `tools.<integration>.<owner>.<connection>.<tool>`\n * handle) instead of an opaque tool id. Storage failures reuse fuma-runtime's\n * `StorageError`/`UniqueViolationError` (`StorageFailure`) — not redefined here. */\n\n// ---------------------------------------------------------------------------\n// Tool lifecycle\n// ---------------------------------------------------------------------------\n\nexport class ToolNotFoundError extends Schema.TaggedErrorClass<ToolNotFoundError>()(\n \"ToolNotFoundError\",\n {\n address: ToolAddress,\n suggestions: Schema.optional(Schema.Array(ToolAddress)),\n },\n) {}\n\nexport class ToolInvocationError extends Schema.TaggedErrorClass<ToolInvocationError>()(\n \"ToolInvocationError\",\n {\n address: ToolAddress,\n message: Schema.String,\n cause: Schema.optional(Schema.Unknown),\n },\n) {}\n\n/** Tool invocation was rejected because a workspace `tool_policy` rule with\n * `action: \"block\"` matched. `pattern` is the matched policy pattern. */\nexport class ToolBlockedError extends Schema.TaggedErrorClass<ToolBlockedError>()(\n \"ToolBlockedError\",\n {\n address: ToolAddress,\n pattern: Schema.String,\n },\n) {}\n\n/** Tool row exists but its owning plugin isn't loaded in this executor config. */\nexport class PluginNotLoadedError extends Schema.TaggedErrorClass<PluginNotLoadedError>()(\n \"PluginNotLoadedError\",\n {\n address: ToolAddress,\n pluginId: Schema.String,\n },\n) {}\n\n/** Tool was found but its owning plugin has no `invokeTool` handler. */\nexport class NoHandlerError extends Schema.TaggedErrorClass<NoHandlerError>()(\"NoHandlerError\", {\n address: ToolAddress,\n pluginId: Schema.String,\n}) {}\n\n// ---------------------------------------------------------------------------\n// Integration / connection lifecycle\n// ---------------------------------------------------------------------------\n\nexport class IntegrationNotFoundError extends Schema.TaggedErrorClass<IntegrationNotFoundError>()(\n \"IntegrationNotFoundError\",\n { slug: IntegrationSlug },\n) {}\n\n/** An \"add integration\" operation targeted a slug (namespace) that is already\n * registered. The core `integrations.register` primitive upserts by design\n * (for idempotent boot re-registration); add-operation layers gate on this to\n * prevent silently clobbering an existing integration's tools, connections,\n * and policies. */\nexport class IntegrationAlreadyExistsError extends Schema.TaggedErrorClass<IntegrationAlreadyExistsError>()(\n \"IntegrationAlreadyExistsError\",\n { slug: IntegrationSlug },\n { httpApiStatus: 409 },\n) {}\n\n/** `integrations.remove` was called on an integration declared statically by a\n * plugin at startup (`canRemove: false`). */\nexport class IntegrationRemovalNotAllowedError extends Schema.TaggedErrorClass<IntegrationRemovalNotAllowedError>()(\n \"IntegrationRemovalNotAllowedError\",\n { slug: IntegrationSlug },\n) {}\n\nexport class ConnectionNotFoundError extends Schema.TaggedErrorClass<ConnectionNotFoundError>()(\n \"ConnectionNotFoundError\",\n {\n owner: Owner,\n integration: IntegrationSlug,\n name: ConnectionName,\n },\n) {}\n\n/** A connection create request was rejected before anything was written: the\n * input is structurally invalid (no credential inputs for a credentialed\n * template, mixed pasted/external origins, …) or targets owner `user` in a\n * context that has no user subject. The message says which — it is safe to\n * show to the caller. */\nexport class InvalidConnectionInputError extends Schema.TaggedErrorClass<InvalidConnectionInputError>()(\n \"InvalidConnectionInputError\",\n { message: Schema.String },\n) {}\n\n/** A connection references a credential provider key that isn't registered on\n * the executor. */\nexport class CredentialProviderNotRegisteredError extends Schema.TaggedErrorClass<CredentialProviderNotRegisteredError>()(\n \"CredentialProviderNotRegisteredError\",\n { provider: ProviderKey },\n) {}\n\n/** A connection's value could not be resolved — the provider returned nothing,\n * or an OAuth token refresh failed and the user must re-auth. */\nexport class CredentialResolutionError extends Schema.TaggedErrorClass<CredentialResolutionError>()(\n \"CredentialResolutionError\",\n {\n owner: Owner,\n integration: IntegrationSlug,\n name: ConnectionName,\n message: Schema.String,\n /** True when the stored grant is permanently invalid and the user must\n * sign in again (RFC 6749 §5.2 invalid_grant and friends). */\n reauthRequired: Schema.optional(Schema.Boolean),\n },\n) {}\n\n// ---------------------------------------------------------------------------\n// Union — the failure channel of `execute`.\n// ---------------------------------------------------------------------------\n\nexport type ExecuteError =\n | ToolNotFoundError\n | ToolInvocationError\n | ToolBlockedError\n | PluginNotLoadedError\n | NoHandlerError\n | ConnectionNotFoundError\n | CredentialProviderNotRegisteredError\n | CredentialResolutionError\n | ElicitationDeclinedError\n | StorageFailure;\n\n/** Convenience union spanning every typed error the SDK raises. */\nexport type ExecutorError =\n | ExecuteError\n | IntegrationNotFoundError\n | IntegrationRemovalNotAllowedError;\n","import type { Effect } from \"effect\";\nimport { Schema } from \"effect\";\n\nimport type { Connection } from \"./connection\";\nimport type { StorageFailure } from \"./fuma-runtime\";\nimport {\n type AuthTemplateSlug,\n type ConnectionName,\n type IntegrationSlug,\n OAuthClientSlug,\n OAuthState,\n type Owner,\n} from \"./ids\";\n\n/* The v2 OAuth surface contracts. OAuth is a credential mechanism, not an\n * integration type. A client is a registered app; running its flow mints a\n * Connection. The client is self-contained (carries its own endpoints) and\n * integration-independent, so the same app can back connections on whatever\n * integrations share that provider.\n *\n * The OAuth 2.1 *implementation* (PKCE, DCR, token exchange + refresh) lives in\n * `oauth-helpers` / `oauth-discovery` / `oauth-service`; these are the public\n * input/output shapes the executor's `oauth.*` namespace speaks. */\n\nexport type OAuthGrant = \"authorization_code\" | \"client_credentials\";\n\n/** Provider OAuth config an integration declares as one of its auth templates —\n * what to request. (The flow itself runs off the self-contained OAuthClient.) */\nexport interface OAuthAuthentication {\n readonly slug: AuthTemplateSlug;\n readonly type: \"oauth\";\n readonly authorizationUrl: string;\n readonly tokenUrl: string;\n readonly scopes: readonly string[];\n}\n\n/** A registered OAuth app — pure app identity: clientId/secret + its endpoints.\n * Owner-scoped: a shared org app or a user's own BYO app. The app does NOT carry\n * scopes — what to request is the INTEGRATION's concern (`OAuthAuthentication.\n * scopes`, surfaced via the declared auth method), so the same app can back any\n * integration without pinning a scope set. */\nexport interface OAuthClient {\n readonly owner: Owner;\n readonly slug: OAuthClientSlug;\n readonly authorizationUrl: string;\n readonly tokenUrl: string;\n readonly grant: OAuthGrant;\n readonly clientId: string;\n /** The literal client secret. Stored out-of-band in the credential provider\n * (vault item id), never inline. Empty string for public / PKCE clients. */\n readonly clientSecret: string;\n /** RFC 8707 Resource Indicator (MCP). Carried so the refresh request can keep\n * the re-minted token bound to the same resource. Null/omitted otherwise. */\n readonly resource?: string | null;\n}\n\nexport type OAuthClientOrigin =\n | { readonly kind: \"manual\" }\n | {\n readonly kind: \"dynamic_client_registration\";\n readonly integration?: IntegrationSlug | null;\n };\n\nexport type CreateOAuthClientInput = OAuthClient & {\n readonly origin?: OAuthClientOrigin;\n};\n\n/** Metadata-only projection of a registered client for listing in the UI.\n * Deliberately omits `clientSecret` — the secret is never returned over the\n * read surface. `clientId` is included (it is not a secret; it is sent in the\n * authorize URL the user's browser visits). */\nexport interface OAuthClientSummary {\n readonly owner: Owner;\n readonly slug: OAuthClientSlug;\n readonly grant: OAuthGrant;\n readonly authorizationUrl: string;\n readonly tokenUrl: string;\n readonly resource?: string | null;\n readonly clientId: string;\n readonly origin: OAuthClientOrigin;\n}\n\n/** Flow-aware result of `oauth.start` — the status says what's next. */\nexport type ConnectResult =\n | { readonly status: \"connected\"; readonly connection: Connection }\n | {\n readonly status: \"redirect\";\n readonly authorizationUrl: string;\n readonly state: OAuthState;\n };\n\n/** Start a flow through a client to mint a connection for one integration.\n * `template` is the integration's oauth template the minted token is applied\n * through. */\nexport interface OAuthStartInput {\n readonly client: OAuthClientSlug;\n /** The owner that owns `client`. Supplied explicitly (the picker knows it), so\n * a Personal connection can be minted through a shared Workspace app without\n * any owner-derivation rule. A Workspace connection must use a Workspace app. */\n readonly clientOwner: Owner;\n /** The owner the minted CONNECTION is saved under (may differ from `clientOwner`). */\n readonly owner: Owner;\n readonly name: ConnectionName;\n readonly integration: IntegrationSlug;\n readonly template: AuthTemplateSlug;\n readonly identityLabel?: string | null;\n /** Browser-facing callback URL for this flow. Defaults to the executor's configured redirectUri. */\n readonly redirectUri?: string | null;\n}\n\nexport interface OAuthCompleteInput {\n readonly state: OAuthState;\n readonly code: string;\n}\n\n/** Probe a base/issuer URL for OAuth 2.1 authorization-server metadata so the\n * onboarding UI can pre-fill a client's endpoints. */\nexport interface OAuthProbeInput {\n readonly url: string;\n}\n\nexport interface OAuthProbeResult {\n readonly authorizationUrl: string;\n readonly tokenUrl: string;\n /** RFC 8707 resource indicator discovered from protected-resource metadata.\n * Persist this on DCR clients so authorize/token/refresh requests stay bound\n * to the protected resource. */\n readonly resource?: string | null;\n readonly scopesSupported?: readonly string[];\n /** Whether the server advertises dynamic client registration (RFC 7591). */\n readonly registrationEndpoint?: string | null;\n /** RFC 8414 `token_endpoint_auth_methods_supported`. Surfaced so DCR can pick\n * a public (\"none\") client when the server allows it. */\n readonly tokenEndpointAuthMethodsSupported?: readonly string[];\n}\n\n/** Mint an OAuth client via RFC 7591 Dynamic Client Registration and persist it.\n * The user pastes NO client id/secret — the authorization server mints a\n * (public, PKCE) client which is stored as an owner-scoped `oauth_client`. */\nexport interface RegisterDynamicClientInput {\n readonly owner: Owner;\n readonly slug: OAuthClientSlug;\n /** RFC 7591 registration endpoint advertised by the authorization server. */\n readonly registrationEndpoint: string;\n readonly authorizationUrl: string;\n readonly tokenUrl: string;\n /** RFC 8707 Resource Indicator (MCP). Persisted on the minted client when known. */\n readonly resource?: string | null;\n readonly scopes: readonly string[];\n /** Auth methods the server advertises. When it allows `none` a public\n * (PKCE-only, no secret) client is registered; otherwise `client_secret_post`. */\n readonly tokenEndpointAuthMethodsSupported?: readonly string[];\n /** Human label for the registered app (RFC 7591 `client_name`). */\n readonly clientName?: string;\n /** Browser-facing callback URL to register. Defaults to the executor's configured redirectUri. */\n readonly redirectUri?: string | null;\n /** Integration that requested this dynamic client, when known. */\n readonly originIntegration?: IntegrationSlug | null;\n}\n\nexport class OAuthStartError extends Schema.TaggedErrorClass<OAuthStartError>()(\"OAuthStartError\", {\n message: Schema.String,\n}) {}\n\nexport class OAuthCompleteError extends Schema.TaggedErrorClass<OAuthCompleteError>()(\n \"OAuthCompleteError\",\n {\n message: Schema.String,\n /** True when the auth-code exchange failed in a way the user must restart. */\n restartRequired: Schema.optional(Schema.Boolean),\n },\n) {}\n\nexport class OAuthProbeError extends Schema.TaggedErrorClass<OAuthProbeError>()(\"OAuthProbeError\", {\n message: Schema.String,\n}) {}\n\nexport class OAuthRegisterDynamicError extends Schema.TaggedErrorClass<OAuthRegisterDynamicError>()(\n \"OAuthRegisterDynamicError\",\n { message: Schema.String },\n) {}\n\nexport class OAuthSessionNotFoundError extends Schema.TaggedErrorClass<OAuthSessionNotFoundError>()(\n \"OAuthSessionNotFoundError\",\n { state: OAuthState },\n) {}\n\n/** The OAuth surface the executor's `oauth.*` namespace and `ctx.oauth` expose.\n * Implemented by `makeOAuthService` (oauth-service.ts), wired by the executor\n * with the deps it needs to mint connections. */\nexport interface OAuthService {\n readonly createClient: (\n input: CreateOAuthClientInput,\n ) => Effect.Effect<OAuthClientSlug, StorageFailure>;\n /** Mint a client via RFC 7591 Dynamic Client Registration (no pre-shared\n * client id/secret) and persist it as an owner-scoped `oauth_client`. */\n readonly registerDynamicClient: (\n input: RegisterDynamicClientInput,\n ) => Effect.Effect<OAuthClientSlug, OAuthRegisterDynamicError | StorageFailure>;\n /** All registered clients visible to the caller (their org's shared clients +\n * their own user clients), as metadata-only summaries — never the secret. */\n readonly listClients: () => Effect.Effect<readonly OAuthClientSummary[], StorageFailure>;\n /** Permanently remove a registered OAuth app, keyed by (owner, slug). The\n * owner policy on `oauth_client` prevents removing another subject's user app.\n * Idempotent: removing an already-gone app succeeds. Connections that\n * referenced the slug keep their stored value and fail at the next token\n * refresh, prompting a reconnect — this op never cascades into connections. */\n readonly removeClient: (\n owner: Owner,\n slug: OAuthClientSlug,\n ) => Effect.Effect<void, StorageFailure>;\n readonly start: (\n input: OAuthStartInput,\n ) => Effect.Effect<ConnectResult, OAuthStartError | StorageFailure>;\n readonly complete: (\n input: OAuthCompleteInput,\n ) => Effect.Effect<Connection, OAuthCompleteError | OAuthSessionNotFoundError | StorageFailure>;\n readonly cancel: (state: OAuthState) => Effect.Effect<void, StorageFailure>;\n readonly probe: (\n input: OAuthProbeInput,\n ) => Effect.Effect<OAuthProbeResult, OAuthProbeError | StorageFailure>;\n}\n","// ---------------------------------------------------------------------------\n// Public projections beyond the core domain types. The integration / connection\n// / tool views live in their own domain files (`integration.ts`, `connection.ts`,\n// `tool.ts`); this file holds the schema-side views and the onboarding URL\n// autodetect result.\n// ---------------------------------------------------------------------------\n\nimport { Schema } from \"effect\";\n\nimport { ToolAddress } from \"./ids\";\n\n// ---------------------------------------------------------------------------\n// ToolSchemaView — the full schema-side view of a tool, returned by\n// `executor.tools.schema(address)`. Includes JSON schema roots plus shared\n// definitions for schema exploration, and optionally TypeScript preview strings.\n// ---------------------------------------------------------------------------\n\nexport const ToolSchemaView = Schema.Struct({\n address: ToolAddress,\n name: Schema.optional(Schema.String),\n description: Schema.optional(Schema.String),\n inputSchema: Schema.optional(Schema.Unknown),\n outputSchema: Schema.optional(Schema.Unknown),\n schemaDefinitions: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n inputTypeScript: Schema.optional(Schema.String),\n outputTypeScript: Schema.optional(Schema.String),\n typeScriptDefinitions: Schema.optional(Schema.Record(Schema.String, Schema.String)),\n});\nexport type ToolSchemaView = typeof ToolSchemaView.Type;\n\n// ---------------------------------------------------------------------------\n// Integration detection — optional capability on `PluginSpec.detect`. When a\n// user pastes a URL in the onboarding UI, `executor.integrations.detect(url)`\n// asks every plugin \"is this yours?\" and returns the best-confidence match so\n// the UI can auto-fill the onboarding form for the right plugin.\n// ---------------------------------------------------------------------------\n\nexport const IntegrationDetectionResult = Schema.Struct({\n /** Plugin id that recognized the URL (e.g. \"openapi\", \"graphql\"). */\n kind: Schema.String,\n /** Confidence tier — UI uses this to pick a winner when multiple plugins\n * claim a URL. */\n confidence: Schema.Literals([\"high\", \"medium\", \"low\"]),\n /** The (possibly normalized) endpoint the plugin will use. */\n endpoint: Schema.String,\n /** Human-readable name suggestion, typically derived from spec title or URL. */\n name: Schema.String,\n /** Slug suggestion — the plugin's recommendation for the integration slug. */\n slug: Schema.String,\n});\nexport type IntegrationDetectionResult = typeof IntegrationDetectionResult.Type;\n"],"mappings":"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","names":["Schema","Schema","Schema","Schema","Schema","Schema","Schema","Schema"]}
1
+ {"version":3,"sources":["../src/policies.ts","../src/elicitation.ts","../src/errors.ts","../src/oauth-client.ts","../src/types.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Tool policies — pattern matcher + policy resolution. Pure functions; the\n// executor stitches them into `tools.list`, `execute`, and the public\n// `executor.policies` CRUD surface. Plugins consume the same surface.\n//\n// v2: policies are owner-scoped (org | user) instead of scope-stacked. Each\n// owner contributes its first matching rule by local position; the final answer\n// is the most restrictive matched action across owners, so a user preference\n// cannot weaken an org guardrail (org = outer, user = inner).\n// ---------------------------------------------------------------------------\n\nimport { Match, Schema } from \"effect\";\n\nimport type { ToolPolicyAction, ToolPolicyRow } from \"./core-schema\";\nimport { Owner, PolicyId } from \"./ids\";\n\nexport interface ToolPolicy {\n readonly id: PolicyId;\n readonly owner: Owner;\n readonly pattern: string;\n readonly action: ToolPolicyAction;\n /** Fractional-indexing key. Lower lex order = higher precedence. */\n readonly position: string;\n readonly createdAt: Date;\n readonly updatedAt: Date;\n}\n\nexport interface CreateToolPolicyInput {\n readonly owner: Owner;\n readonly pattern: string;\n /** Optional explicit position. Defaults to a key above the current minimum\n * (top of the owner's list; highest precedence). */\n readonly action: ToolPolicyAction;\n readonly position?: string;\n}\n\nexport interface UpdateToolPolicyInput {\n readonly id: string;\n readonly owner: Owner;\n readonly pattern?: string;\n readonly action?: ToolPolicyAction;\n readonly position?: string;\n}\n\nexport interface RemoveToolPolicyInput {\n readonly id: string;\n readonly owner: Owner;\n}\n\n// ---------------------------------------------------------------------------\n// Match result.\n// ---------------------------------------------------------------------------\n\nexport interface PolicyMatch {\n readonly action: ToolPolicyAction;\n readonly pattern: string;\n readonly policyId: string;\n}\n\nexport type PolicySource = \"user\" | \"plugin-default\";\n\nexport interface EffectivePolicy {\n readonly action: ToolPolicyAction;\n readonly source: PolicySource;\n readonly pattern?: string;\n readonly policyId?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Pattern matching. Grammar (matched against the full tool address\n// `<integration>.<owner>.<connection>.<tool>` or a shorter form the executor\n// passes in):\n// - universal: `*`\n// - exact: `vercel.dns.create`\n// - subtree (trailing `*`): `vercel.dns.*` — the literal prefix plus anything deeper\n// - plugin-wide: `vercel.*`\n// - mid-segment `*`: `vercel.*.*.dns.create` — each NON-trailing `*` matches\n// EXACTLY ONE segment (e.g. wildcard the owner/connection\n// segments to target a tool across every connection).\n// A `*` is always a complete segment: mid-pattern it consumes one segment,\n// trailing it is a subtree. Partial wildcards (`me*`) and a leading `*` (other\n// than the universal `*`) are rejected by `isValidPattern`.\n// ---------------------------------------------------------------------------\n\nexport const matchPattern = (pattern: string, toolId: string): boolean => {\n if (pattern === \"*\") return true;\n const patternSegments = pattern.split(\".\");\n const toolSegments = toolId.split(\".\");\n for (let i = 0; i < patternSegments.length; i++) {\n const seg = patternSegments[i]!;\n if (seg === \"*\") {\n // Trailing `*` is a subtree: the literal prefix already matched, so the\n // address matches at this position and anything deeper (or nothing).\n if (i === patternSegments.length - 1) return toolSegments.length >= i;\n // A non-trailing `*` consumes EXACTLY ONE segment; one must exist here.\n if (i >= toolSegments.length) return false;\n continue;\n }\n if (i >= toolSegments.length || toolSegments[i] !== seg) return false;\n }\n // Pattern exhausted with no trailing `*`: an exact match requires equal length.\n return patternSegments.length === toolSegments.length;\n};\n\nexport const isValidPattern = (pattern: string): boolean => {\n if (pattern.length === 0) return false;\n if (pattern === \"*\") return true;\n if (pattern.startsWith(\".\") || pattern.endsWith(\".\")) return false;\n if (pattern.includes(\"..\")) return false;\n if (pattern.startsWith(\"*\")) return false;\n const segments = pattern.split(\".\");\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i]!;\n if (seg.length === 0) return false;\n // A `*` segment must be the WHOLE segment — no partial wildcards (`me*`).\n // A `*` is valid mid-pattern (one segment) or trailing (subtree).\n if (seg.includes(\"*\") && seg !== \"*\") return false;\n }\n return true;\n};\n\n// ---------------------------------------------------------------------------\n// Resolution — each owner contributes its first matching rule by local\n// position; the most restrictive matched action across owners wins. Caller\n// passes an `ownerRank` so the resolver doesn't need to know which owner is\n// the outer guardrail.\n// ---------------------------------------------------------------------------\n\nexport const comparePolicyRow = (\n a: Pick<ToolPolicyRow, \"position\" | \"id\">,\n b: Pick<ToolPolicyRow, \"position\" | \"id\">,\n): number => {\n const pa = a.position;\n const pb = b.position;\n if (pa < pb) return -1;\n if (pa > pb) return 1;\n const ia = a.id;\n const ib = b.id;\n return ia < ib ? -1 : ia > ib ? 1 : 0;\n};\n\nconst actionRestrictionRank = (action: ToolPolicyAction): number =>\n Match.value(action).pipe(\n Match.when(\"block\", () => 3),\n Match.when(\"require_approval\", () => 2),\n Match.when(\"approve\", () => 1),\n Match.exhaustive,\n );\n\nconst moreRestrictive = <T extends { readonly action: ToolPolicyAction }>(\n current: T | undefined,\n candidate: T,\n): T => {\n if (!current) return candidate;\n const currentRank = actionRestrictionRank(current.action);\n const candidateRank = actionRestrictionRank(candidate.action);\n return candidateRank > currentRank ? candidate : current;\n};\n\nexport const resolveToolPolicy = (\n toolId: string,\n policies: readonly ToolPolicyRow[],\n ownerRank: (row: Pick<ToolPolicyRow, \"owner\">) => number,\n): PolicyMatch | undefined => {\n if (policies.length === 0) return undefined;\n const sorted = [...policies].sort((a, b) => {\n const sa = ownerRank(a);\n const sb = ownerRank(b);\n if (sa !== sb) return sa - sb;\n return comparePolicyRow(a, b);\n });\n const firstMatchByOwner = new Map<string, PolicyMatch>();\n for (const row of sorted) {\n if (firstMatchByOwner.has(row.owner)) continue;\n if (matchPattern(row.pattern, toolId)) {\n firstMatchByOwner.set(row.owner, {\n action: row.action as ToolPolicyAction,\n pattern: row.pattern,\n policyId: row.id,\n });\n }\n }\n let selected: PolicyMatch | undefined;\n for (const match of firstMatchByOwner.values()) {\n selected = moreRestrictive(selected, match);\n }\n return selected;\n};\n\n// ---------------------------------------------------------------------------\n// Layered resolution — user-authored rules + plugin default `requiresApproval`.\n// ---------------------------------------------------------------------------\n\nconst liftPlugin = (defaultRequiresApproval: boolean | undefined): EffectivePolicy =>\n defaultRequiresApproval\n ? { action: \"require_approval\", source: \"plugin-default\" }\n : { action: \"approve\", source: \"plugin-default\" };\n\nconst liftUser = (match: PolicyMatch): EffectivePolicy => ({\n action: match.action,\n source: \"user\",\n pattern: match.pattern,\n policyId: match.policyId,\n});\n\nexport const resolveEffectivePolicy = (\n toolId: string,\n policies: readonly ToolPolicyRow[],\n ownerRank: (row: Pick<ToolPolicyRow, \"owner\">) => number,\n defaultRequiresApproval?: boolean,\n): EffectivePolicy => {\n const match = resolveToolPolicy(toolId, policies, ownerRank);\n return match ? liftUser(match) : liftPlugin(defaultRequiresApproval);\n};\n\nexport const effectivePolicyFromSorted = (\n toolId: string,\n sortedPolicies: readonly (Pick<ToolPolicy, \"pattern\" | \"action\" | \"id\"> &\n Partial<Pick<ToolPolicy, \"owner\">>)[],\n defaultRequiresApproval?: boolean,\n): EffectivePolicy => {\n const firstMatchByOwner = new Map<string, EffectivePolicy>();\n for (const p of sortedPolicies) {\n const ownerKey = \"owner\" in p && p.owner ? String(p.owner) : \"__flat__\";\n if (firstMatchByOwner.has(ownerKey)) continue;\n if (matchPattern(p.pattern, toolId)) {\n firstMatchByOwner.set(ownerKey, {\n action: p.action,\n source: \"user\",\n pattern: p.pattern,\n policyId: p.id,\n });\n }\n }\n let selected: EffectivePolicy | undefined;\n for (const match of firstMatchByOwner.values()) {\n selected = moreRestrictive(selected, match);\n }\n return selected ?? liftPlugin(defaultRequiresApproval);\n};\n\n// ---------------------------------------------------------------------------\n// Row → public projection.\n// ---------------------------------------------------------------------------\n\nexport const rowToToolPolicy = (row: ToolPolicyRow): ToolPolicy => ({\n id: PolicyId.make(row.id),\n owner: row.owner as Owner,\n pattern: row.pattern,\n action: row.action as ToolPolicyAction,\n position: row.position,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n});\n\nexport const ToolPolicyActionSchema = Schema.Literals([\"approve\", \"require_approval\", \"block\"]);\n","import { Effect, Schema } from \"effect\";\n\nimport { ElicitationId, ToolAddress } from \"./ids\";\n\n/* A tool that needs user input mid-call suspends and the host's `onElicitation`\n * handler (executor-level, overridable per `execute`) answers. Tools that never\n * elicit never trigger it. Schema-tagged so requests/responses cross the wire. */\n\n/** Tool needs structured input from the user (render a form). */\nexport const FormElicitation = Schema.TaggedStruct(\"FormElicitation\", {\n message: Schema.String,\n /** JSON Schema describing the fields to collect. */\n requestedSchema: Schema.Record(Schema.String, Schema.Unknown),\n});\nexport type FormElicitation = typeof FormElicitation.Type;\n\n/** Tool needs the user to visit a URL (OAuth, approval page, etc.). */\nexport const UrlElicitation = Schema.TaggedStruct(\"UrlElicitation\", {\n message: Schema.String,\n url: Schema.String,\n /** Unique id so the host can correlate the callback. */\n elicitationId: ElicitationId,\n});\nexport type UrlElicitation = typeof UrlElicitation.Type;\n\nexport type ElicitationRequest = FormElicitation | UrlElicitation;\n\nexport const ElicitationAction = Schema.Literals([\"accept\", \"decline\", \"cancel\"]);\nexport type ElicitationAction = typeof ElicitationAction.Type;\n\nexport const ElicitationResponse = Schema.Struct({\n action: ElicitationAction,\n /** Present when `action` is \"accept\" — the data the user provided. */\n content: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n});\nexport type ElicitationResponse = typeof ElicitationResponse.Type;\n\n/** Handler input — the tool address being invoked, its args, and the request. */\nexport interface ElicitationContext {\n readonly address: ToolAddress;\n readonly args: unknown;\n readonly request: ElicitationRequest;\n}\n\n/** Host-provided handler the SDK calls when a tool suspends for input. */\nexport type ElicitationHandler = (ctx: ElicitationContext) => Effect.Effect<ElicitationResponse>;\n\n/** Executor-level elicitation policy: a handler, or `\"accept-all\"` to\n * auto-accept every request (tests / non-interactive hosts). */\nexport type OnElicitation = ElicitationHandler | \"accept-all\";\n\n/** Per-call options for `execute`. */\nexport interface InvokeOptions {\n /** Override the executor-level handler for this single call. */\n readonly onElicitation?: OnElicitation;\n}\n\n/** A tool was declined or cancelled during elicitation. */\nexport class ElicitationDeclinedError extends Schema.TaggedErrorClass<ElicitationDeclinedError>()(\n \"ElicitationDeclinedError\",\n {\n address: ToolAddress,\n action: Schema.Literals([\"decline\", \"cancel\"]),\n },\n) {}\n","import { Schema } from \"effect\";\n\nimport { ElicitationDeclinedError } from \"./elicitation\";\nimport type { StorageFailure } from \"./fuma-runtime\";\nimport { ConnectionName, IntegrationSlug, Owner, ProviderKey, ToolAddress } from \"./ids\";\n\n/* The failure set the SDK surfaces. `execute`'s invoke failures are ported from\n * v1 but re-keyed by `address` (the full `tools.<integration>.<owner>.<connection>.<tool>`\n * handle) instead of an opaque tool id. Storage failures reuse fuma-runtime's\n * `StorageError`/`UniqueViolationError` (`StorageFailure`) — not redefined here. */\n\n// ---------------------------------------------------------------------------\n// Tool lifecycle\n// ---------------------------------------------------------------------------\n\nexport class ToolNotFoundError extends Schema.TaggedErrorClass<ToolNotFoundError>()(\n \"ToolNotFoundError\",\n {\n address: ToolAddress,\n suggestions: Schema.optional(Schema.Array(ToolAddress)),\n },\n) {}\n\nexport class ToolInvocationError extends Schema.TaggedErrorClass<ToolInvocationError>()(\n \"ToolInvocationError\",\n {\n address: ToolAddress,\n message: Schema.String,\n cause: Schema.optional(Schema.Unknown),\n },\n) {}\n\n/** Tool invocation was rejected because a workspace `tool_policy` rule with\n * `action: \"block\"` matched. `pattern` is the matched policy pattern. */\nexport class ToolBlockedError extends Schema.TaggedErrorClass<ToolBlockedError>()(\n \"ToolBlockedError\",\n {\n address: ToolAddress,\n pattern: Schema.String,\n },\n) {}\n\n/** Tool row exists but its owning plugin isn't loaded in this executor config. */\nexport class PluginNotLoadedError extends Schema.TaggedErrorClass<PluginNotLoadedError>()(\n \"PluginNotLoadedError\",\n {\n address: ToolAddress,\n pluginId: Schema.String,\n },\n) {}\n\n/** Tool was found but its owning plugin has no `invokeTool` handler. */\nexport class NoHandlerError extends Schema.TaggedErrorClass<NoHandlerError>()(\"NoHandlerError\", {\n address: ToolAddress,\n pluginId: Schema.String,\n}) {}\n\n// ---------------------------------------------------------------------------\n// Integration / connection lifecycle\n// ---------------------------------------------------------------------------\n\nexport class IntegrationNotFoundError extends Schema.TaggedErrorClass<IntegrationNotFoundError>()(\n \"IntegrationNotFoundError\",\n { slug: IntegrationSlug },\n) {}\n\n/** An \"add integration\" operation targeted a slug (namespace) that is already\n * registered. The core `integrations.register` primitive upserts by design\n * (for idempotent boot re-registration); add-operation layers gate on this to\n * prevent silently clobbering an existing integration's tools, connections,\n * and policies. */\nexport class IntegrationAlreadyExistsError extends Schema.TaggedErrorClass<IntegrationAlreadyExistsError>()(\n \"IntegrationAlreadyExistsError\",\n { slug: IntegrationSlug },\n { httpApiStatus: 409 },\n) {}\n\n/** `integrations.remove` was called on an integration declared statically by a\n * plugin at startup (`canRemove: false`). */\nexport class IntegrationRemovalNotAllowedError extends Schema.TaggedErrorClass<IntegrationRemovalNotAllowedError>()(\n \"IntegrationRemovalNotAllowedError\",\n { slug: IntegrationSlug },\n) {}\n\nexport class ConnectionNotFoundError extends Schema.TaggedErrorClass<ConnectionNotFoundError>()(\n \"ConnectionNotFoundError\",\n {\n owner: Owner,\n integration: IntegrationSlug,\n name: ConnectionName,\n },\n) {}\n\n/** A connection create request was rejected before anything was written: the\n * input is structurally invalid (no credential inputs for a credentialed\n * template, mixed pasted/external origins, …) or targets owner `user` in a\n * context that has no user subject. The message says which — it is safe to\n * show to the caller. */\nexport class InvalidConnectionInputError extends Schema.TaggedErrorClass<InvalidConnectionInputError>()(\n \"InvalidConnectionInputError\",\n { message: Schema.String },\n) {}\n\n/** A connection references a credential provider key that isn't registered on\n * the executor. */\nexport class CredentialProviderNotRegisteredError extends Schema.TaggedErrorClass<CredentialProviderNotRegisteredError>()(\n \"CredentialProviderNotRegisteredError\",\n { provider: ProviderKey },\n) {}\n\n/** A connection's value could not be resolved — the provider returned nothing,\n * or an OAuth token refresh failed and the user must re-auth. */\nexport class CredentialResolutionError extends Schema.TaggedErrorClass<CredentialResolutionError>()(\n \"CredentialResolutionError\",\n {\n owner: Owner,\n integration: IntegrationSlug,\n name: ConnectionName,\n message: Schema.String,\n /** True when the stored grant is permanently invalid and the user must\n * sign in again (RFC 6749 §5.2 invalid_grant and friends). */\n reauthRequired: Schema.optional(Schema.Boolean),\n },\n) {}\n\n// ---------------------------------------------------------------------------\n// Union — the failure channel of `execute`.\n// ---------------------------------------------------------------------------\n\nexport type ExecuteError =\n | ToolNotFoundError\n | ToolInvocationError\n | ToolBlockedError\n | PluginNotLoadedError\n | NoHandlerError\n | ConnectionNotFoundError\n | CredentialProviderNotRegisteredError\n | CredentialResolutionError\n | ElicitationDeclinedError\n | StorageFailure;\n\n/** Convenience union spanning every typed error the SDK raises. */\nexport type ExecutorError =\n | ExecuteError\n | IntegrationNotFoundError\n | IntegrationRemovalNotAllowedError;\n","import type { Effect } from \"effect\";\nimport { Schema } from \"effect\";\n\nimport type { Connection } from \"./connection\";\nimport type { StorageFailure } from \"./fuma-runtime\";\nimport {\n type AuthTemplateSlug,\n type ConnectionName,\n type IntegrationSlug,\n OAuthClientSlug,\n OAuthState,\n type Owner,\n} from \"./ids\";\n\n/* The v2 OAuth surface contracts. OAuth is a credential mechanism, not an\n * integration type. A client is a registered app; running its flow mints a\n * Connection. The client is self-contained (carries its own endpoints) and\n * integration-independent, so the same app can back connections on whatever\n * integrations share that provider.\n *\n * The OAuth 2.1 *implementation* (PKCE, DCR, token exchange + refresh) lives in\n * `oauth-helpers` / `oauth-discovery` / `oauth-service`; these are the public\n * input/output shapes the executor's `oauth.*` namespace speaks. */\n\nexport type OAuthGrant = \"authorization_code\" | \"client_credentials\";\n\n/** Provider OAuth config an integration declares as one of its auth templates —\n * what to request. (The flow itself runs off the self-contained OAuthClient.)\n * Keyed `kind: \"oauth2\"` like every auth method across the plugins. */\nexport interface OAuthAuthentication {\n readonly slug: AuthTemplateSlug;\n readonly kind: \"oauth2\";\n readonly authorizationUrl: string;\n readonly tokenUrl: string;\n readonly scopes: readonly string[];\n}\n\n/** A registered OAuth app — pure app identity: clientId/secret + its endpoints.\n * Owner-scoped: a shared org app or a user's own BYO app. The app does NOT carry\n * scopes — what to request is the INTEGRATION's concern (`OAuthAuthentication.\n * scopes`, surfaced via the declared auth method), so the same app can back any\n * integration without pinning a scope set. */\nexport interface OAuthClient {\n readonly owner: Owner;\n readonly slug: OAuthClientSlug;\n readonly authorizationUrl: string;\n readonly tokenUrl: string;\n readonly grant: OAuthGrant;\n readonly clientId: string;\n /** The literal client secret. Stored out-of-band in the credential provider\n * (vault item id), never inline. Empty string for public / PKCE clients. */\n readonly clientSecret: string;\n /** RFC 8707 Resource Indicator (MCP). Carried so the refresh request can keep\n * the re-minted token bound to the same resource. Null/omitted otherwise. */\n readonly resource?: string | null;\n}\n\nexport type OAuthClientOrigin =\n | { readonly kind: \"manual\" }\n | {\n readonly kind: \"dynamic_client_registration\";\n readonly integration?: IntegrationSlug | null;\n };\n\nexport type CreateOAuthClientInput = OAuthClient & {\n readonly origin?: OAuthClientOrigin;\n};\n\n/** Metadata-only projection of a registered client for listing in the UI.\n * Deliberately omits `clientSecret` — the secret is never returned over the\n * read surface. `clientId` is included (it is not a secret; it is sent in the\n * authorize URL the user's browser visits). */\nexport interface OAuthClientSummary {\n readonly owner: Owner;\n readonly slug: OAuthClientSlug;\n readonly grant: OAuthGrant;\n readonly authorizationUrl: string;\n readonly tokenUrl: string;\n readonly resource?: string | null;\n readonly clientId: string;\n readonly origin: OAuthClientOrigin;\n}\n\n/** Flow-aware result of `oauth.start` — the status says what's next. */\nexport type ConnectResult =\n | { readonly status: \"connected\"; readonly connection: Connection }\n | {\n readonly status: \"redirect\";\n readonly authorizationUrl: string;\n readonly state: OAuthState;\n };\n\n/** Start a flow through a client to mint a connection for one integration.\n * `template` is the integration's oauth template the minted token is applied\n * through. */\nexport interface OAuthStartInput {\n readonly client: OAuthClientSlug;\n /** The owner that owns `client`. Supplied explicitly (the picker knows it), so\n * a Personal connection can be minted through a shared Workspace app without\n * any owner-derivation rule. A Workspace connection must use a Workspace app. */\n readonly clientOwner: Owner;\n /** The owner the minted CONNECTION is saved under (may differ from `clientOwner`). */\n readonly owner: Owner;\n readonly name: ConnectionName;\n readonly integration: IntegrationSlug;\n readonly template: AuthTemplateSlug;\n readonly identityLabel?: string | null;\n /** Browser-facing callback URL for this flow. Defaults to the executor's configured redirectUri. */\n readonly redirectUri?: string | null;\n}\n\nexport interface OAuthCompleteInput {\n readonly state: OAuthState;\n readonly code: string;\n}\n\n/** Probe a base/issuer URL for OAuth 2.1 authorization-server metadata so the\n * onboarding UI can pre-fill a client's endpoints. */\nexport interface OAuthProbeInput {\n readonly url: string;\n}\n\nexport interface OAuthProbeResult {\n readonly authorizationUrl: string;\n readonly tokenUrl: string;\n /** RFC 8707 resource indicator discovered from protected-resource metadata.\n * Persist this on DCR clients so authorize/token/refresh requests stay bound\n * to the protected resource. */\n readonly resource?: string | null;\n readonly scopesSupported?: readonly string[];\n /** Whether the server advertises dynamic client registration (RFC 7591). */\n readonly registrationEndpoint?: string | null;\n /** RFC 8414 `token_endpoint_auth_methods_supported`. Surfaced so DCR can pick\n * a public (\"none\") client when the server allows it. */\n readonly tokenEndpointAuthMethodsSupported?: readonly string[];\n}\n\n/** Mint an OAuth client via RFC 7591 Dynamic Client Registration and persist it.\n * The user pastes NO client id/secret — the authorization server mints a\n * (public, PKCE) client which is stored as an owner-scoped `oauth_client`. */\nexport interface RegisterDynamicClientInput {\n readonly owner: Owner;\n readonly slug: OAuthClientSlug;\n /** RFC 7591 registration endpoint advertised by the authorization server. */\n readonly registrationEndpoint: string;\n readonly authorizationUrl: string;\n readonly tokenUrl: string;\n /** RFC 8707 Resource Indicator (MCP). Persisted on the minted client when known. */\n readonly resource?: string | null;\n readonly scopes: readonly string[];\n /** Auth methods the server advertises. When it allows `none` a public\n * (PKCE-only, no secret) client is registered; otherwise `client_secret_post`. */\n readonly tokenEndpointAuthMethodsSupported?: readonly string[];\n /** Human label for the registered app (RFC 7591 `client_name`). */\n readonly clientName?: string;\n /** Browser-facing callback URL to register. Defaults to the executor's configured redirectUri. */\n readonly redirectUri?: string | null;\n /** Integration that requested this dynamic client, when known. */\n readonly originIntegration?: IntegrationSlug | null;\n}\n\nexport class OAuthStartError extends Schema.TaggedErrorClass<OAuthStartError>()(\"OAuthStartError\", {\n message: Schema.String,\n}) {}\n\nexport class OAuthCompleteError extends Schema.TaggedErrorClass<OAuthCompleteError>()(\n \"OAuthCompleteError\",\n {\n message: Schema.String,\n /** True when the auth-code exchange failed in a way the user must restart. */\n restartRequired: Schema.optional(Schema.Boolean),\n },\n) {}\n\nexport class OAuthProbeError extends Schema.TaggedErrorClass<OAuthProbeError>()(\"OAuthProbeError\", {\n message: Schema.String,\n}) {}\n\nexport class OAuthRegisterDynamicError extends Schema.TaggedErrorClass<OAuthRegisterDynamicError>()(\n \"OAuthRegisterDynamicError\",\n { message: Schema.String },\n) {}\n\nexport class OAuthSessionNotFoundError extends Schema.TaggedErrorClass<OAuthSessionNotFoundError>()(\n \"OAuthSessionNotFoundError\",\n { state: OAuthState },\n) {}\n\n/** The OAuth surface the executor's `oauth.*` namespace and `ctx.oauth` expose.\n * Implemented by `makeOAuthService` (oauth-service.ts), wired by the executor\n * with the deps it needs to mint connections. */\nexport interface OAuthService {\n readonly createClient: (\n input: CreateOAuthClientInput,\n ) => Effect.Effect<OAuthClientSlug, StorageFailure>;\n /** Mint a client via RFC 7591 Dynamic Client Registration (no pre-shared\n * client id/secret) and persist it as an owner-scoped `oauth_client`. */\n readonly registerDynamicClient: (\n input: RegisterDynamicClientInput,\n ) => Effect.Effect<OAuthClientSlug, OAuthRegisterDynamicError | StorageFailure>;\n /** All registered clients visible to the caller (their org's shared clients +\n * their own user clients), as metadata-only summaries — never the secret. */\n readonly listClients: () => Effect.Effect<readonly OAuthClientSummary[], StorageFailure>;\n /** Permanently remove a registered OAuth app, keyed by (owner, slug). The\n * owner policy on `oauth_client` prevents removing another subject's user app.\n * Idempotent: removing an already-gone app succeeds. Connections that\n * referenced the slug keep their stored value and fail at the next token\n * refresh, prompting a reconnect — this op never cascades into connections. */\n readonly removeClient: (\n owner: Owner,\n slug: OAuthClientSlug,\n ) => Effect.Effect<void, StorageFailure>;\n readonly start: (\n input: OAuthStartInput,\n ) => Effect.Effect<ConnectResult, OAuthStartError | StorageFailure>;\n readonly complete: (\n input: OAuthCompleteInput,\n ) => Effect.Effect<Connection, OAuthCompleteError | OAuthSessionNotFoundError | StorageFailure>;\n readonly cancel: (state: OAuthState) => Effect.Effect<void, StorageFailure>;\n readonly probe: (\n input: OAuthProbeInput,\n ) => Effect.Effect<OAuthProbeResult, OAuthProbeError | StorageFailure>;\n}\n","// ---------------------------------------------------------------------------\n// Public projections beyond the core domain types. The integration / connection\n// / tool views live in their own domain files (`integration.ts`, `connection.ts`,\n// `tool.ts`); this file holds the schema-side views and the onboarding URL\n// autodetect result.\n// ---------------------------------------------------------------------------\n\nimport { Schema } from \"effect\";\n\nimport { ToolAddress } from \"./ids\";\n\n// ---------------------------------------------------------------------------\n// ToolSchemaView — the full schema-side view of a tool, returned by\n// `executor.tools.schema(address)`. Includes JSON schema roots plus shared\n// definitions for schema exploration, and optionally TypeScript preview strings.\n// ---------------------------------------------------------------------------\n\nexport const ToolSchemaView = Schema.Struct({\n address: ToolAddress,\n name: Schema.optional(Schema.String),\n description: Schema.optional(Schema.String),\n inputSchema: Schema.optional(Schema.Unknown),\n outputSchema: Schema.optional(Schema.Unknown),\n schemaDefinitions: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n inputTypeScript: Schema.optional(Schema.String),\n outputTypeScript: Schema.optional(Schema.String),\n typeScriptDefinitions: Schema.optional(Schema.Record(Schema.String, Schema.String)),\n});\nexport type ToolSchemaView = typeof ToolSchemaView.Type;\n\n// ---------------------------------------------------------------------------\n// Integration detection — optional capability on `PluginSpec.detect`. When a\n// user pastes a URL in the onboarding UI, `executor.integrations.detect(url)`\n// asks every plugin \"is this yours?\" and returns the best-confidence match so\n// the UI can auto-fill the onboarding form for the right plugin.\n// ---------------------------------------------------------------------------\n\nexport const IntegrationDetectionResult = Schema.Struct({\n /** Plugin id that recognized the URL (e.g. \"openapi\", \"graphql\"). */\n kind: Schema.String,\n /** Confidence tier — UI uses this to pick a winner when multiple plugins\n * claim a URL. */\n confidence: Schema.Literals([\"high\", \"medium\", \"low\"]),\n /** The (possibly normalized) endpoint the plugin will use. */\n endpoint: Schema.String,\n /** Human-readable name suggestion, typically derived from spec title or URL. */\n name: Schema.String,\n /** Slug suggestion — the plugin's recommendation for the integration slug. */\n slug: Schema.String,\n});\nexport type IntegrationDetectionResult = typeof IntegrationDetectionResult.Type;\n"],"mappings":"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","names":["Schema","Schema","Schema","Schema","Schema","Schema","Schema","Schema"]}
@@ -24,7 +24,7 @@ import {
24
24
  isValidPattern,
25
25
  resolveEffectivePolicy,
26
26
  rowToToolPolicy
27
- } from "./chunk-3RRMGXEN.js";
27
+ } from "./chunk-UKOTOKXM.js";
28
28
  import {
29
29
  OAUTH2_DEFAULT_TIMEOUT_MS,
30
30
  assertSupportedOAuthEndpointUrl,
@@ -233,6 +233,12 @@ var makeInMemoryBlobStore = () => {
233
233
  has: (ns, key) => Effect2.sync(() => store.has(k(ns, key)))
234
234
  };
235
235
  };
236
+ var sha256Hex = (text) => Effect2.promise(async () => {
237
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(text));
238
+ return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join(
239
+ ""
240
+ );
241
+ });
236
242
  var blobId = (namespace, key) => JSON.stringify([namespace, key]);
237
243
  var toBlobRows = (rows) => rows;
238
244
  var makeFumaBlobStore = (fuma) => ({
@@ -642,6 +648,19 @@ var coreTables = defineTables({
642
648
  })
643
649
  });
644
650
  var coreSchema = coreTables;
651
+ var TOOL_INVOCATION_COLUMNS = [
652
+ "tenant",
653
+ "owner",
654
+ "subject",
655
+ "integration",
656
+ "connection",
657
+ "plugin_id",
658
+ "name",
659
+ "description",
660
+ "annotations",
661
+ "created_at",
662
+ "updated_at"
663
+ ];
645
664
  var TOOL_POLICY_ACTIONS = [
646
665
  "approve",
647
666
  "require_approval",
@@ -5038,7 +5057,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
5038
5057
  const rootDb = withQueryContext(rootDbUntyped, ownerContext);
5039
5058
  const fuma = makeFumaClient(rootDb);
5040
5059
  const core = makeCoreDb(fuma);
5041
- const blobs = makeFumaBlobStore(fuma);
5060
+ const blobs = config.blobs ?? makeFumaBlobStore(fuma);
5042
5061
  const transaction = (effect) => fuma.transaction(effect);
5043
5062
  const staticTools = /* @__PURE__ */ new Map();
5044
5063
  const runtimes = /* @__PURE__ */ new Map();
@@ -5256,14 +5275,7 @@ var createExecutor = (config) => Effect7.gen(function* () {
5256
5275
  const resolveConnectionValue = (row) => resolveConnectionValues(row).pipe(
5257
5276
  Effect7.map((values) => values[PRIMARY_INPUT_VARIABLE] ?? null)
5258
5277
  );
5259
- const resolveConnectionValueByRef = (ref) => Effect7.gen(function* () {
5260
- const row = yield* findConnectionRow(ref);
5261
- if (!row) return null;
5262
- return yield* resolveConnectionValue(row);
5263
- }).pipe(
5264
- // The plugin-facing contract (`ctx.connections.resolveValue`, `getValue`)
5265
- // is `StorageFailure`-typed; fold a reauth-required resolution failure
5266
- // into a StorageError so the public surface stays stable.
5278
+ const foldResolutionFailure = (effect) => effect.pipe(
5267
5279
  Effect7.catchTag(
5268
5280
  "CredentialResolutionError",
5269
5281
  (err) => Effect7.fail(
@@ -5275,6 +5287,20 @@ var createExecutor = (config) => Effect7.gen(function* () {
5275
5287
  )
5276
5288
  )
5277
5289
  );
5290
+ const resolveConnectionValueByRef = (ref) => foldResolutionFailure(
5291
+ Effect7.gen(function* () {
5292
+ const row = yield* findConnectionRow(ref);
5293
+ if (!row) return null;
5294
+ return yield* resolveConnectionValue(row);
5295
+ })
5296
+ );
5297
+ const resolveConnectionValuesByRef = (ref) => foldResolutionFailure(
5298
+ Effect7.gen(function* () {
5299
+ const row = yield* findConnectionRow(ref);
5300
+ if (!row) return {};
5301
+ return yield* resolveConnectionValues(row);
5302
+ })
5303
+ );
5278
5304
  const findIntegrationRow = (slug) => core.findFirst("integration", {
5279
5305
  where: (b) => b("slug", "=", String(slug))
5280
5306
  });
@@ -5428,7 +5454,10 @@ var createExecutor = (config) => Effect7.gen(function* () {
5428
5454
  integration: rowToIntegration(integrationRow),
5429
5455
  config: decodeJsonColumn(integrationRow.config),
5430
5456
  connection: ref,
5431
- getValue: () => resolveConnectionValueByRef(ref)
5457
+ template: existingRow ? AuthTemplateSlug.make(existingRow.template) : null,
5458
+ storage: runtime.storage,
5459
+ getValue: () => resolveConnectionValueByRef(ref),
5460
+ getValues: () => resolveConnectionValuesByRef(ref)
5432
5461
  }).pipe(
5433
5462
  Effect7.mapError(
5434
5463
  (cause) => pluginStorageFailure(integrationRow.plugin_id, "resolveTools", cause)
@@ -5803,7 +5832,8 @@ var createExecutor = (config) => Effect7.gen(function* () {
5803
5832
  filter?.integration === void 0 ? true : b("integration", "=", String(filter.integration)),
5804
5833
  filter?.owner === void 0 ? true : b("owner", "=", filter.owner),
5805
5834
  filter?.connection === void 0 ? true : b("connection", "=", String(filter.connection))
5806
- )
5835
+ ),
5836
+ select: TOOL_INVOCATION_COLUMNS
5807
5837
  });
5808
5838
  const includeBlocked = filter?.includeBlocked ?? false;
5809
5839
  const policyRows = yield* core.findMany("tool_policy", {});
@@ -6061,12 +6091,14 @@ ${approvalArgumentPreview(args)}`,
6061
6091
  )
6062
6092
  ),
6063
6093
  orderBy: ["name", "asc"],
6064
- limit: TOOL_SUGGESTION_LIMIT
6094
+ limit: TOOL_SUGGESTION_LIMIT,
6095
+ select: TOOL_INVOCATION_COLUMNS
6065
6096
  });
6066
6097
  const findToolRowsForConnection = (parsed) => core.findMany("tool", {
6067
6098
  where: toolRowsForConnectionWhere(parsed),
6068
6099
  orderBy: ["name", "asc"],
6069
- limit: TOOL_SUGGESTION_LIMIT
6100
+ limit: TOOL_SUGGESTION_LIMIT,
6101
+ select: TOOL_INVOCATION_COLUMNS
6070
6102
  });
6071
6103
  const execute = (address, args, options) => {
6072
6104
  const handler = pickHandler(options);
@@ -6117,7 +6149,8 @@ ${approvalArgumentPreview(args)}`,
6117
6149
  b("integration", "=", String(parsed.integration)),
6118
6150
  b("connection", "=", String(parsed.connection)),
6119
6151
  b("name", "=", String(parsed.tool))
6120
- )
6152
+ ),
6153
+ select: TOOL_INVOCATION_COLUMNS
6121
6154
  });
6122
6155
  if (!row) {
6123
6156
  const searchMatches = yield* searchToolRowsForConnection(parsed);
@@ -6413,6 +6446,7 @@ export {
6413
6446
  isStorageFailure,
6414
6447
  pluginBlobStore,
6415
6448
  makeInMemoryBlobStore,
6449
+ sha256Hex,
6416
6450
  makeFumaBlobStore,
6417
6451
  tool,
6418
6452
  definePlugin,
@@ -6444,4 +6478,4 @@ export {
6444
6478
  collectTables,
6445
6479
  createExecutor
6446
6480
  };
6447
- //# sourceMappingURL=chunk-WN6EB76P.js.map
6481
+ //# sourceMappingURL=chunk-YPVKRUZV.js.map