@executor-js/sdk 1.4.28 → 1.4.30
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.
- package/dist/blob.d.ts +2 -1
- package/dist/blob.d.ts.map +1 -1
- package/dist/chunk-2LU3SC64.js +7 -0
- package/dist/chunk-2LU3SC64.js.map +1 -0
- package/dist/chunk-7D4SUZUM.js +38 -0
- package/dist/chunk-7D4SUZUM.js.map +1 -0
- package/dist/chunk-B4YGTZF6.js +22 -0
- package/dist/chunk-B4YGTZF6.js.map +1 -0
- package/dist/chunk-BZNIRSMG.js +7873 -0
- package/dist/chunk-BZNIRSMG.js.map +1 -0
- package/dist/chunk-ECMCGZYE.js +5814 -0
- package/dist/chunk-ECMCGZYE.js.map +1 -0
- package/dist/{chunk-6SQWMOM4.js → chunk-MLNVNVRI.js} +2 -6
- package/dist/chunk-MLNVNVRI.js.map +1 -0
- package/dist/chunk-P2WKYAC5.js +1 -0
- package/dist/chunk-P2WKYAC5.js.map +1 -0
- package/dist/chunk-ZANQD7E2.js +1035 -0
- package/dist/chunk-ZANQD7E2.js.map +1 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +3 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/core-schema.d.ts +283 -408
- package/dist/core-schema.d.ts.map +1 -1
- package/dist/core-tools.d.ts +6 -0
- package/dist/core-tools.d.ts.map +1 -0
- package/dist/core.js +120 -168
- package/dist/core.js.map +1 -1
- package/dist/credential-bindings.d.ts +86 -24
- package/dist/credential-bindings.d.ts.map +1 -1
- package/dist/errors.d.ts +1 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/executor.d.ts +46 -12
- package/dist/executor.d.ts.map +1 -1
- package/dist/fuma-runtime.d.ts +50 -0
- package/dist/fuma-runtime.d.ts.map +1 -0
- package/dist/http-source.d.ts +109 -0
- package/dist/http-source.d.ts.map +1 -0
- package/dist/http-source.js +155 -0
- package/dist/http-source.js.map +1 -0
- package/dist/index.d.ts +17 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -21
- package/dist/index.js.map +1 -1
- package/dist/oauth-service.d.ts +2 -10
- package/dist/oauth-service.d.ts.map +1 -1
- package/dist/oauth.d.ts +9 -1
- package/dist/oauth.d.ts.map +1 -1
- package/dist/plugin-storage.d.ts +40 -0
- package/dist/plugin-storage.d.ts.map +1 -0
- package/dist/plugin.d.ts +110 -34
- package/dist/plugin.d.ts.map +1 -1
- package/dist/promise-executor.d.ts +33 -8
- package/dist/promise-executor.d.ts.map +1 -1
- package/dist/promise.d.ts +3 -3
- package/dist/promise.d.ts.map +1 -1
- package/dist/schema-refs.d.ts +1 -0
- package/dist/schema-refs.d.ts.map +1 -1
- package/dist/schema-refs.test.d.ts +2 -0
- package/dist/schema-refs.test.d.ts.map +1 -0
- package/dist/schema-types.d.ts +22 -8
- package/dist/schema-types.d.ts.map +1 -1
- package/dist/scope-policy.d.ts +23 -0
- package/dist/scope-policy.d.ts.map +1 -0
- package/dist/scope-policy.test.d.ts +2 -0
- package/dist/scope-policy.test.d.ts.map +1 -0
- package/dist/scope.d.ts +10 -0
- package/dist/scope.d.ts.map +1 -1
- package/dist/secrets.d.ts +1 -1
- package/dist/secrets.d.ts.map +1 -1
- package/dist/shared.d.ts +13 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +103 -0
- package/dist/shared.js.map +1 -0
- package/dist/sqlite-test-db-OK2WQNR5.js +8 -0
- package/dist/sqlite-test-db-OK2WQNR5.js.map +1 -0
- package/dist/sqlite-test-db.d.ts +22 -0
- package/dist/sqlite-test-db.d.ts.map +1 -0
- package/dist/test-config.d.ts +45 -4
- package/dist/test-config.d.ts.map +1 -1
- package/dist/testing/oauth-test-server.d.ts +80 -0
- package/dist/testing/oauth-test-server.d.ts.map +1 -0
- package/dist/testing.d.ts +4 -1
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +706 -18
- package/dist/testing.js.map +1 -1
- package/dist/testing.test.d.ts +2 -0
- package/dist/testing.test.d.ts.map +1 -0
- package/dist/tool-result.d.ts +22 -0
- package/dist/tool-result.d.ts.map +1 -0
- package/dist/tool-result.test.d.ts +2 -0
- package/dist/tool-result.test.d.ts.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vendor/json-schema-to-typescript/applySchemaTyping.d.ts +3 -0
- package/dist/vendor/json-schema-to-typescript/applySchemaTyping.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/compat.d.ts +10 -0
- package/dist/vendor/json-schema-to-typescript/compat.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/formatter.d.ts +3 -0
- package/dist/vendor/json-schema-to-typescript/formatter.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/generator.d.ts +7 -0
- package/dist/vendor/json-schema-to-typescript/generator.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/index.d.ts +93 -0
- package/dist/vendor/json-schema-to-typescript/index.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/linker.d.ts +8 -0
- package/dist/vendor/json-schema-to-typescript/linker.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/normalizer.d.ts +5 -0
- package/dist/vendor/json-schema-to-typescript/normalizer.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/optimizer.d.ts +4 -0
- package/dist/vendor/json-schema-to-typescript/optimizer.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/optionValidator.d.ts +3 -0
- package/dist/vendor/json-schema-to-typescript/optionValidator.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/parser.d.ts +8 -0
- package/dist/vendor/json-schema-to-typescript/parser.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/resolver.d.ts +7 -0
- package/dist/vendor/json-schema-to-typescript/resolver.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/types/AST.d.ts +108 -0
- package/dist/vendor/json-schema-to-typescript/types/AST.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/types/JSONSchema.d.ts +103 -0
- package/dist/vendor/json-schema-to-typescript/types/JSONSchema.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/types/json-schema.d.ts +34 -0
- package/dist/vendor/json-schema-to-typescript/types/json-schema.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/typesOfSchema.d.ts +11 -0
- package/dist/vendor/json-schema-to-typescript/typesOfSchema.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/utils.d.ts +30 -0
- package/dist/vendor/json-schema-to-typescript/utils.d.ts.map +1 -0
- package/dist/vendor/json-schema-to-typescript/validator.d.ts +3 -0
- package/dist/vendor/json-schema-to-typescript/validator.d.ts.map +1 -0
- package/package.json +17 -2
- package/dist/chunk-6SQWMOM4.js.map +0 -1
- package/dist/chunk-I2OEQ2GJ.js +0 -103
- package/dist/chunk-I2OEQ2GJ.js.map +0 -1
- package/dist/chunk-OIJL6F6M.js +0 -5507
- package/dist/chunk-OIJL6F6M.js.map +0 -1
- package/dist/error-handling.test.d.ts +0 -2
- package/dist/error-handling.test.d.ts.map +0 -1
- package/dist/scoped-adapter.d.ts +0 -28
- package/dist/scoped-adapter.d.ts.map +0 -1
- package/dist/scoped-adapter.test.d.ts +0 -2
- package/dist/scoped-adapter.test.d.ts.map +0 -1
|
@@ -0,0 +1,1035 @@
|
|
|
1
|
+
// src/fuma-runtime.ts
|
|
2
|
+
import { Cause, Context, Data, Effect, Exit, Layer, Predicate } from "effect";
|
|
3
|
+
var StorageError = class extends Data.TaggedError("StorageError") {
|
|
4
|
+
};
|
|
5
|
+
var UniqueViolationError = class extends Data.TaggedError("UniqueViolationError") {
|
|
6
|
+
};
|
|
7
|
+
var isUniqueViolation = (cause) => {
|
|
8
|
+
let current = cause;
|
|
9
|
+
for (let i = 0; i < 5; i += 1) {
|
|
10
|
+
const err = current && typeof current === "object" ? current : null;
|
|
11
|
+
if (!err) return false;
|
|
12
|
+
const code = err["code"];
|
|
13
|
+
const message = err["message"];
|
|
14
|
+
const innerCause = err["cause"];
|
|
15
|
+
if (code === "23505") return true;
|
|
16
|
+
if (typeof message === "string" && /unique constraint|duplicate key|violates unique constraint/i.test(message)) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
if (!innerCause || innerCause === current) return false;
|
|
20
|
+
current = innerCause;
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
};
|
|
24
|
+
var causeMessage = (cause) => {
|
|
25
|
+
const message = cause && typeof cause === "object" ? (
|
|
26
|
+
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: preserve database driver error text inside typed StorageError
|
|
27
|
+
cause["message"]
|
|
28
|
+
) : void 0;
|
|
29
|
+
return typeof message === "string" && message.length > 0 ? message : void 0;
|
|
30
|
+
};
|
|
31
|
+
var isStorageFailure = (error) => Predicate.isTagged(error, "StorageError") || Predicate.isTagged(error, "UniqueViolationError");
|
|
32
|
+
var fumaFailureFromCause = (label, cause) => {
|
|
33
|
+
if (isStorageFailure(cause)) return cause;
|
|
34
|
+
if (isUniqueViolation(cause)) return new UniqueViolationError({ model: label });
|
|
35
|
+
return new StorageError({
|
|
36
|
+
message: causeMessage(cause) ?? `FumaDB operation failed: ${label}`,
|
|
37
|
+
cause
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
var fumaEffect = (label, run) => Effect.tryPromise({
|
|
41
|
+
try: run,
|
|
42
|
+
catch: (cause) => fumaFailureFromCause(label, cause)
|
|
43
|
+
});
|
|
44
|
+
var activeFumaDbRef = Context.Reference("executor/ActiveFumaDb", {
|
|
45
|
+
defaultValue: () => null
|
|
46
|
+
});
|
|
47
|
+
var TransactionEffectFailure = class {
|
|
48
|
+
constructor(error) {
|
|
49
|
+
this.error = error;
|
|
50
|
+
}
|
|
51
|
+
error;
|
|
52
|
+
};
|
|
53
|
+
var TransactionEffectDefect = class {
|
|
54
|
+
constructor(cause) {
|
|
55
|
+
this.cause = cause;
|
|
56
|
+
}
|
|
57
|
+
cause;
|
|
58
|
+
};
|
|
59
|
+
var isAllowedTable = (tables, table2) => tables === void 0 || typeof table2 === "string" && tables.has(table2);
|
|
60
|
+
var assertAllowedTable = (tables, table2) => {
|
|
61
|
+
if (isAllowedTable(tables, table2)) return;
|
|
62
|
+
throw new StorageError({
|
|
63
|
+
message: `FumaDB table "${String(table2)}" is not available through this storage boundary.`,
|
|
64
|
+
cause: void 0
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
var makeSafeFumaQuery = (db, options) => {
|
|
68
|
+
const table2 = (name) => {
|
|
69
|
+
assertAllowedTable(options.tables, name);
|
|
70
|
+
return name;
|
|
71
|
+
};
|
|
72
|
+
const query = {
|
|
73
|
+
count: (name, value) => db.count(table2(name), value),
|
|
74
|
+
create: (name, value) => db.create(table2(name), value),
|
|
75
|
+
createMany: (name, values) => db.createMany(table2(name), values),
|
|
76
|
+
deleteMany: (name, value) => db.deleteMany(table2(name), value),
|
|
77
|
+
findFirst: (name, value) => db.findFirst(table2(name), value),
|
|
78
|
+
findMany: (name, value) => db.findMany(table2(name), value),
|
|
79
|
+
transaction: (run) => db.transaction((transactionDb) => run(makeSafeFumaQuery(transactionDb, options))),
|
|
80
|
+
updateMany: (name, value) => db.updateMany(table2(name), value),
|
|
81
|
+
upsert: (name, value) => db.upsert(table2(name), value)
|
|
82
|
+
};
|
|
83
|
+
return Object.freeze(query);
|
|
84
|
+
};
|
|
85
|
+
var makeFumaClient = (db, options = {}) => {
|
|
86
|
+
const use = (label, fn) => Effect.flatMap(
|
|
87
|
+
Effect.service(activeFumaDbRef),
|
|
88
|
+
(active) => fumaEffect(label, () => fn(makeSafeFumaQuery(active ?? db, options)))
|
|
89
|
+
).pipe(Effect.withSpan(`fumadb.${label}`));
|
|
90
|
+
const transaction = (effect) => Effect.flatMap(Effect.service(activeFumaDbRef), (active) => {
|
|
91
|
+
if (active) return effect;
|
|
92
|
+
return Effect.tryPromise({
|
|
93
|
+
try: () => db.transaction(async (transactionDb) => {
|
|
94
|
+
const exit = await Effect.runPromiseExit(
|
|
95
|
+
effect.pipe(Effect.provideService(activeFumaDbRef, transactionDb))
|
|
96
|
+
);
|
|
97
|
+
if (Exit.isSuccess(exit)) return exit.value;
|
|
98
|
+
const failure = exit.cause.reasons.find(Cause.isFailReason);
|
|
99
|
+
if (failure) throw new TransactionEffectFailure(failure.error);
|
|
100
|
+
throw new TransactionEffectDefect(exit.cause);
|
|
101
|
+
}),
|
|
102
|
+
catch: (cause) => {
|
|
103
|
+
if (cause instanceof TransactionEffectFailure) return cause.error;
|
|
104
|
+
if (cause instanceof TransactionEffectDefect) {
|
|
105
|
+
return fumaFailureFromCause("transaction", cause.cause);
|
|
106
|
+
}
|
|
107
|
+
return fumaFailureFromCause("transaction", cause);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}).pipe(Effect.withSpan("fumadb.transaction"));
|
|
111
|
+
return { use, transaction };
|
|
112
|
+
};
|
|
113
|
+
var FumaClient = class extends Context.Service()("executor/FumaClient") {
|
|
114
|
+
static layer = (db) => Layer.succeed(this)(makeFumaClient(db));
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// src/ids.ts
|
|
118
|
+
import { Schema } from "effect";
|
|
119
|
+
var ScopeId = Schema.String.pipe(Schema.brand("ScopeId"));
|
|
120
|
+
var ToolId = Schema.String.pipe(Schema.brand("ToolId"));
|
|
121
|
+
var SecretId = Schema.String.pipe(Schema.brand("SecretId"));
|
|
122
|
+
var PolicyId = Schema.String.pipe(Schema.brand("PolicyId"));
|
|
123
|
+
var ConnectionId = Schema.String.pipe(Schema.brand("ConnectionId"));
|
|
124
|
+
var CredentialBindingId = Schema.String.pipe(Schema.brand("CredentialBindingId"));
|
|
125
|
+
|
|
126
|
+
// src/core-schema.ts
|
|
127
|
+
import { column, idColumn, table } from "fumadb/schema";
|
|
128
|
+
|
|
129
|
+
// src/scope-policy.ts
|
|
130
|
+
import { ConditionType } from "fumadb/query";
|
|
131
|
+
var executorScopePolicyName = "executor.scope";
|
|
132
|
+
var executorUnscopedPolicyName = "executor.unscoped";
|
|
133
|
+
var unscopedExecutorTables = /* @__PURE__ */ new Set(["blob"]);
|
|
134
|
+
var scopePolicyViolation = (message) => {
|
|
135
|
+
throw new StorageError({ message, cause: void 0 });
|
|
136
|
+
};
|
|
137
|
+
function assertExecutorScopePolicyTable(table2, tableKey) {
|
|
138
|
+
const tableName = table2.ormName || tableKey || table2.names.sql;
|
|
139
|
+
const scopedPolicy = table2.policies.find((policy) => policy.name === executorScopePolicyName);
|
|
140
|
+
if (scopedPolicy?.onRead && scopedPolicy.onCreate && scopedPolicy.onUpdate && scopedPolicy.onDelete) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const unscopedPolicy = table2.policies.find(
|
|
144
|
+
(policy) => policy.name === executorUnscopedPolicyName
|
|
145
|
+
);
|
|
146
|
+
if (unscopedPolicy && unscopedExecutorTables.has(tableName)) return;
|
|
147
|
+
scopePolicyViolation(`Storage table "${tableName}" is missing an executor scope policy.`);
|
|
148
|
+
}
|
|
149
|
+
var requireExecutorScopeContext = (tableName, access, context) => {
|
|
150
|
+
if (context) return context;
|
|
151
|
+
return scopePolicyViolation(
|
|
152
|
+
`Storage ${access} on table "${tableName}" is missing executor scope context.`
|
|
153
|
+
);
|
|
154
|
+
};
|
|
155
|
+
var isExecutorScopeAllowed = (tableName, access, value, context) => {
|
|
156
|
+
const scopeContext = requireExecutorScopeContext(tableName, access, context);
|
|
157
|
+
return typeof value === "string" && scopeContext.allowedScopeIds.has(value);
|
|
158
|
+
};
|
|
159
|
+
var executorScopeIds = (tableName, access, context) => [...requireExecutorScopeContext(tableName, access, context).allowedScopeIds];
|
|
160
|
+
var findScopeTarget = (condition, columns) => {
|
|
161
|
+
if (!condition) return null;
|
|
162
|
+
if (condition.type === ConditionType.Compare) {
|
|
163
|
+
const column2 = columns.find((name) => condition.a.ormName === name);
|
|
164
|
+
if (!column2 || condition.operator !== "=" || typeof condition.b !== "string") return null;
|
|
165
|
+
return { column: column2, value: condition.b };
|
|
166
|
+
}
|
|
167
|
+
if (condition.type !== ConditionType.And) return null;
|
|
168
|
+
for (const item of condition.items) {
|
|
169
|
+
const target = findScopeTarget(item, columns);
|
|
170
|
+
if (target) return target;
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
};
|
|
174
|
+
var requireExecutorScopeTarget = (tableName, access, where, context, columns = ["scope_id"]) => {
|
|
175
|
+
const scopeContext = requireExecutorScopeContext(tableName, access, context);
|
|
176
|
+
const target = findScopeTarget(where, columns);
|
|
177
|
+
if (target && scopeContext.allowedScopeIds.has(target.value)) return target;
|
|
178
|
+
return scopePolicyViolation(
|
|
179
|
+
`Storage ${access} on table "${tableName}" must target an explicit scope in the executor scope stack.`
|
|
180
|
+
);
|
|
181
|
+
};
|
|
182
|
+
var assertExecutorScopeAllowed = (tableName, access, value, context) => {
|
|
183
|
+
if (isExecutorScopeAllowed(tableName, access, value, context)) return;
|
|
184
|
+
scopePolicyViolation(
|
|
185
|
+
`Storage ${access} on table "${tableName}" is outside the executor scope stack.`
|
|
186
|
+
);
|
|
187
|
+
};
|
|
188
|
+
var assertExecutorScopeTargetValue = (tableName, access, value, target, context) => {
|
|
189
|
+
assertExecutorScopeAllowed(tableName, access, value, context);
|
|
190
|
+
if (value === target.value) return;
|
|
191
|
+
scopePolicyViolation(
|
|
192
|
+
`Storage ${access} on table "${tableName}" must write the same scope it explicitly targets.`
|
|
193
|
+
);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// src/core-schema.ts
|
|
197
|
+
var textColumn = (name) => column(name, "string");
|
|
198
|
+
var nullableTextColumn = (name) => column(name, "string").nullable();
|
|
199
|
+
var boolColumn = (name, defaultValue) => column(name, "bool").defaultTo(defaultValue);
|
|
200
|
+
var bigintColumn = (name) => column(name, "bigint");
|
|
201
|
+
var nullableBigintColumn = (name) => column(name, "bigint").nullable();
|
|
202
|
+
var jsonColumn = (name) => column(name, "json");
|
|
203
|
+
var nullableJsonColumn = (name) => column(name, "json").nullable();
|
|
204
|
+
var dateColumn = (name) => column(name, "timestamp");
|
|
205
|
+
var unscopedExecutorTable = (name, columns) => {
|
|
206
|
+
const out = table(name, {
|
|
207
|
+
...columns,
|
|
208
|
+
row_id: idColumn("row_id", "varchar(255)").defaultTo$("auto"),
|
|
209
|
+
id: column("id", "varchar(255)")
|
|
210
|
+
});
|
|
211
|
+
out.unique(`${name}_id_uidx`, ["id"]);
|
|
212
|
+
return out.policy({
|
|
213
|
+
name: executorUnscopedPolicyName
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
var scopedExecutorTableBase = (name, columns) => {
|
|
217
|
+
const out = table(name, {
|
|
218
|
+
...columns,
|
|
219
|
+
row_id: idColumn("row_id", "varchar(255)").defaultTo$("auto"),
|
|
220
|
+
id: column("id", "varchar(255)"),
|
|
221
|
+
scope_id: column("scope_id", "varchar(255)")
|
|
222
|
+
});
|
|
223
|
+
out.unique(`${name}_scope_id_id_uidx`, ["scope_id", "id"]);
|
|
224
|
+
return out;
|
|
225
|
+
};
|
|
226
|
+
var scopedExecutorTable = (name, columns) => {
|
|
227
|
+
const out = scopedExecutorTableBase(name, columns);
|
|
228
|
+
return out.policy({
|
|
229
|
+
name: executorScopePolicyName,
|
|
230
|
+
onRead: ({ builder, context }) => builder("scope_id", "in", executorScopeIds(name, "read", context)),
|
|
231
|
+
onCreate: ({ values, context }) => assertExecutorScopeAllowed(name, "write", values.scope_id, context),
|
|
232
|
+
onUpdate: ({ builder, set, create, where, context }) => {
|
|
233
|
+
const target = requireExecutorScopeTarget(name, "write", where, context);
|
|
234
|
+
if (set.scope_id !== void 0) {
|
|
235
|
+
assertExecutorScopeTargetValue(name, "write", set.scope_id, target, context);
|
|
236
|
+
}
|
|
237
|
+
if (create?.scope_id !== void 0) {
|
|
238
|
+
assertExecutorScopeTargetValue(name, "write", create.scope_id, target, context);
|
|
239
|
+
}
|
|
240
|
+
return builder("scope_id", "=", target.value);
|
|
241
|
+
},
|
|
242
|
+
onDelete: ({ builder, where, context }) => {
|
|
243
|
+
const target = requireExecutorScopeTarget(name, "delete", where, context);
|
|
244
|
+
return builder("scope_id", "=", target.value);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
};
|
|
248
|
+
var defineTables = (tables) => tables;
|
|
249
|
+
var credentialBindingKinds = ["text", "secret", "connection"];
|
|
250
|
+
var credentialBindingTable = (() => {
|
|
251
|
+
const out = scopedExecutorTableBase("credential_binding", {
|
|
252
|
+
plugin_id: textColumn("plugin_id"),
|
|
253
|
+
source_id: textColumn("source_id"),
|
|
254
|
+
source_scope_id: textColumn("source_scope_id"),
|
|
255
|
+
slot_key: textColumn("slot_key"),
|
|
256
|
+
kind: textColumn("kind"),
|
|
257
|
+
text_value: nullableTextColumn("text_value"),
|
|
258
|
+
secret_id: nullableTextColumn("secret_id"),
|
|
259
|
+
secret_scope_id: nullableTextColumn("secret_scope_id"),
|
|
260
|
+
connection_id: nullableTextColumn("connection_id"),
|
|
261
|
+
created_at: dateColumn("created_at"),
|
|
262
|
+
updated_at: dateColumn("updated_at")
|
|
263
|
+
});
|
|
264
|
+
return out.policy({
|
|
265
|
+
name: executorScopePolicyName,
|
|
266
|
+
onRead: ({ builder, context }) => builder("scope_id", "in", executorScopeIds("credential_binding", "read", context)),
|
|
267
|
+
onCreate: ({ values, context }) => assertExecutorScopeAllowed("credential_binding", "write", values.scope_id, context),
|
|
268
|
+
onUpdate: ({ builder, set, create, where, context }) => {
|
|
269
|
+
const target = requireExecutorScopeTarget("credential_binding", "write", where, context);
|
|
270
|
+
if (set.scope_id !== void 0) {
|
|
271
|
+
assertExecutorScopeTargetValue(
|
|
272
|
+
"credential_binding",
|
|
273
|
+
"write",
|
|
274
|
+
set.scope_id,
|
|
275
|
+
target,
|
|
276
|
+
context
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
if (create?.scope_id !== void 0) {
|
|
280
|
+
assertExecutorScopeTargetValue(
|
|
281
|
+
"credential_binding",
|
|
282
|
+
"write",
|
|
283
|
+
create.scope_id,
|
|
284
|
+
target,
|
|
285
|
+
context
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
return builder("scope_id", "=", target.value);
|
|
289
|
+
},
|
|
290
|
+
onDelete: ({ builder, where, context }) => {
|
|
291
|
+
const target = requireExecutorScopeTarget("credential_binding", "delete", where, context, [
|
|
292
|
+
"scope_id",
|
|
293
|
+
"source_scope_id"
|
|
294
|
+
]);
|
|
295
|
+
return builder(target.column, "=", target.value);
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
})();
|
|
299
|
+
var coreTables = defineTables({
|
|
300
|
+
source: scopedExecutorTable("source", {
|
|
301
|
+
plugin_id: textColumn("plugin_id"),
|
|
302
|
+
kind: textColumn("kind"),
|
|
303
|
+
name: textColumn("name"),
|
|
304
|
+
url: nullableTextColumn("url"),
|
|
305
|
+
can_remove: boolColumn("can_remove", true),
|
|
306
|
+
can_refresh: boolColumn("can_refresh", false),
|
|
307
|
+
can_edit: boolColumn("can_edit", false),
|
|
308
|
+
created_at: dateColumn("created_at"),
|
|
309
|
+
updated_at: dateColumn("updated_at")
|
|
310
|
+
}),
|
|
311
|
+
tool: scopedExecutorTable("tool", {
|
|
312
|
+
source_id: textColumn("source_id"),
|
|
313
|
+
plugin_id: textColumn("plugin_id"),
|
|
314
|
+
name: textColumn("name"),
|
|
315
|
+
description: textColumn("description"),
|
|
316
|
+
input_schema: nullableJsonColumn("input_schema"),
|
|
317
|
+
output_schema: nullableJsonColumn("output_schema"),
|
|
318
|
+
created_at: dateColumn("created_at"),
|
|
319
|
+
updated_at: dateColumn("updated_at")
|
|
320
|
+
}),
|
|
321
|
+
definition: scopedExecutorTable("definition", {
|
|
322
|
+
source_id: textColumn("source_id"),
|
|
323
|
+
plugin_id: textColumn("plugin_id"),
|
|
324
|
+
name: textColumn("name"),
|
|
325
|
+
schema: jsonColumn("schema"),
|
|
326
|
+
created_at: dateColumn("created_at")
|
|
327
|
+
}),
|
|
328
|
+
secret: scopedExecutorTable("secret", {
|
|
329
|
+
name: textColumn("name"),
|
|
330
|
+
provider: textColumn("provider"),
|
|
331
|
+
owned_by_connection_id: nullableTextColumn("owned_by_connection_id"),
|
|
332
|
+
created_at: dateColumn("created_at")
|
|
333
|
+
}),
|
|
334
|
+
connection: scopedExecutorTable("connection", {
|
|
335
|
+
provider: textColumn("provider"),
|
|
336
|
+
identity_label: nullableTextColumn("identity_label"),
|
|
337
|
+
access_token_secret_id: textColumn("access_token_secret_id"),
|
|
338
|
+
refresh_token_secret_id: nullableTextColumn("refresh_token_secret_id"),
|
|
339
|
+
expires_at: nullableBigintColumn("expires_at"),
|
|
340
|
+
scope: nullableTextColumn("scope"),
|
|
341
|
+
provider_state: nullableJsonColumn("provider_state"),
|
|
342
|
+
created_at: dateColumn("created_at"),
|
|
343
|
+
updated_at: dateColumn("updated_at")
|
|
344
|
+
}),
|
|
345
|
+
oauth2_session: scopedExecutorTable("oauth2_session", {
|
|
346
|
+
plugin_id: textColumn("plugin_id"),
|
|
347
|
+
strategy: textColumn("strategy"),
|
|
348
|
+
connection_id: textColumn("connection_id"),
|
|
349
|
+
token_scope: textColumn("token_scope"),
|
|
350
|
+
redirect_url: textColumn("redirect_url"),
|
|
351
|
+
payload: jsonColumn("payload"),
|
|
352
|
+
expires_at: bigintColumn("expires_at"),
|
|
353
|
+
created_at: dateColumn("created_at")
|
|
354
|
+
}),
|
|
355
|
+
credential_binding: credentialBindingTable,
|
|
356
|
+
plugin_storage: scopedExecutorTable("plugin_storage", {
|
|
357
|
+
plugin_id: textColumn("plugin_id"),
|
|
358
|
+
collection: textColumn("collection"),
|
|
359
|
+
key: textColumn("key"),
|
|
360
|
+
data: jsonColumn("data"),
|
|
361
|
+
created_at: dateColumn("created_at"),
|
|
362
|
+
updated_at: dateColumn("updated_at")
|
|
363
|
+
}),
|
|
364
|
+
tool_policy: scopedExecutorTable("tool_policy", {
|
|
365
|
+
pattern: textColumn("pattern"),
|
|
366
|
+
action: textColumn("action"),
|
|
367
|
+
position: textColumn("position"),
|
|
368
|
+
created_at: dateColumn("created_at"),
|
|
369
|
+
updated_at: dateColumn("updated_at")
|
|
370
|
+
}),
|
|
371
|
+
blob: unscopedExecutorTable("blob", {
|
|
372
|
+
namespace: textColumn("namespace"),
|
|
373
|
+
key: textColumn("key"),
|
|
374
|
+
value: textColumn("value")
|
|
375
|
+
})
|
|
376
|
+
});
|
|
377
|
+
var coreSchema = coreTables;
|
|
378
|
+
var TOOL_POLICY_ACTIONS = [
|
|
379
|
+
"approve",
|
|
380
|
+
"require_approval",
|
|
381
|
+
"block"
|
|
382
|
+
];
|
|
383
|
+
var isToolPolicyAction = (value) => typeof value === "string" && TOOL_POLICY_ACTIONS.includes(value);
|
|
384
|
+
|
|
385
|
+
// src/credential-bindings.ts
|
|
386
|
+
import { Match, Schema as Schema2 } from "effect";
|
|
387
|
+
var CredentialBindingKind = Schema2.Literals(credentialBindingKinds);
|
|
388
|
+
var CredentialBindingValue = Schema2.Union([
|
|
389
|
+
Schema2.Struct({
|
|
390
|
+
kind: Schema2.Literal("text"),
|
|
391
|
+
text: Schema2.String
|
|
392
|
+
}),
|
|
393
|
+
Schema2.Struct({
|
|
394
|
+
kind: Schema2.Literal("secret"),
|
|
395
|
+
secretId: SecretId,
|
|
396
|
+
secretScopeId: Schema2.optional(ScopeId)
|
|
397
|
+
}),
|
|
398
|
+
Schema2.Struct({
|
|
399
|
+
kind: Schema2.Literal("connection"),
|
|
400
|
+
connectionId: ConnectionId
|
|
401
|
+
})
|
|
402
|
+
]);
|
|
403
|
+
var ConfiguredCredentialBinding = Schema2.Struct({
|
|
404
|
+
kind: Schema2.Literal("binding"),
|
|
405
|
+
slot: Schema2.String,
|
|
406
|
+
prefix: Schema2.optional(Schema2.String)
|
|
407
|
+
});
|
|
408
|
+
var ConfiguredCredentialValue = Schema2.Union([Schema2.String, ConfiguredCredentialBinding]);
|
|
409
|
+
var ScopedSecretCredentialInput = Schema2.Struct({
|
|
410
|
+
secretId: Schema2.String,
|
|
411
|
+
prefix: Schema2.optional(Schema2.String),
|
|
412
|
+
targetScope: ScopeId,
|
|
413
|
+
secretScopeId: Schema2.optional(ScopeId)
|
|
414
|
+
});
|
|
415
|
+
var CredentialBindingRef = Schema2.Struct({
|
|
416
|
+
id: CredentialBindingId,
|
|
417
|
+
scopeId: ScopeId,
|
|
418
|
+
pluginId: Schema2.String,
|
|
419
|
+
sourceId: Schema2.String,
|
|
420
|
+
sourceScopeId: ScopeId,
|
|
421
|
+
slotKey: Schema2.String,
|
|
422
|
+
value: CredentialBindingValue,
|
|
423
|
+
createdAt: Schema2.Date,
|
|
424
|
+
updatedAt: Schema2.Date
|
|
425
|
+
});
|
|
426
|
+
var CredentialBindingSourceInput = Schema2.Struct({
|
|
427
|
+
pluginId: Schema2.String,
|
|
428
|
+
sourceId: Schema2.String,
|
|
429
|
+
sourceScope: ScopeId
|
|
430
|
+
});
|
|
431
|
+
var CredentialBindingSlotInput = Schema2.Struct({
|
|
432
|
+
pluginId: Schema2.String,
|
|
433
|
+
sourceId: Schema2.String,
|
|
434
|
+
sourceScope: ScopeId,
|
|
435
|
+
slotKey: Schema2.String
|
|
436
|
+
});
|
|
437
|
+
var RemoveCredentialBindingInput = Schema2.Struct({
|
|
438
|
+
targetScope: ScopeId,
|
|
439
|
+
pluginId: Schema2.String,
|
|
440
|
+
sourceId: Schema2.String,
|
|
441
|
+
sourceScope: ScopeId,
|
|
442
|
+
slotKey: Schema2.String
|
|
443
|
+
});
|
|
444
|
+
var ReplaceCredentialBindingValue = Schema2.Struct({
|
|
445
|
+
slotKey: Schema2.String,
|
|
446
|
+
value: CredentialBindingValue
|
|
447
|
+
});
|
|
448
|
+
var ReplaceCredentialBindingsInput = Schema2.Struct({
|
|
449
|
+
targetScope: ScopeId,
|
|
450
|
+
pluginId: Schema2.String,
|
|
451
|
+
sourceId: Schema2.String,
|
|
452
|
+
sourceScope: ScopeId,
|
|
453
|
+
slotPrefixes: Schema2.Array(Schema2.String),
|
|
454
|
+
bindings: Schema2.Array(ReplaceCredentialBindingValue)
|
|
455
|
+
});
|
|
456
|
+
var SourceCredentialBindingSource = Schema2.Struct({
|
|
457
|
+
id: Schema2.String,
|
|
458
|
+
scope: ScopeId
|
|
459
|
+
});
|
|
460
|
+
var SourceCredentialBindingSourceInput = Schema2.Struct({
|
|
461
|
+
source: SourceCredentialBindingSource
|
|
462
|
+
});
|
|
463
|
+
var SourceCredentialBindingSlotInput = Schema2.Struct({
|
|
464
|
+
source: SourceCredentialBindingSource,
|
|
465
|
+
slotKey: Schema2.String
|
|
466
|
+
});
|
|
467
|
+
var SetSourceCredentialBindingInput = Schema2.Struct({
|
|
468
|
+
scope: ScopeId,
|
|
469
|
+
source: SourceCredentialBindingSource,
|
|
470
|
+
slotKey: Schema2.String,
|
|
471
|
+
value: CredentialBindingValue
|
|
472
|
+
});
|
|
473
|
+
var RemoveSourceCredentialBindingInput = Schema2.Struct({
|
|
474
|
+
scope: ScopeId,
|
|
475
|
+
source: SourceCredentialBindingSource,
|
|
476
|
+
slotKey: Schema2.String
|
|
477
|
+
});
|
|
478
|
+
var ReplaceSourceCredentialBindingsInput = Schema2.Struct({
|
|
479
|
+
scope: ScopeId,
|
|
480
|
+
source: SourceCredentialBindingSource,
|
|
481
|
+
slotPrefixes: Schema2.Array(Schema2.String),
|
|
482
|
+
bindings: Schema2.Array(ReplaceCredentialBindingValue)
|
|
483
|
+
});
|
|
484
|
+
var CredentialBindingResolutionStatus = Schema2.Literals([
|
|
485
|
+
"resolved",
|
|
486
|
+
"missing",
|
|
487
|
+
"blocked"
|
|
488
|
+
]);
|
|
489
|
+
var ResolvedCredentialSlot = Schema2.Struct({
|
|
490
|
+
pluginId: Schema2.String,
|
|
491
|
+
sourceId: Schema2.String,
|
|
492
|
+
sourceScopeId: ScopeId,
|
|
493
|
+
slotKey: Schema2.String,
|
|
494
|
+
bindingScopeId: Schema2.NullOr(ScopeId),
|
|
495
|
+
kind: Schema2.NullOr(CredentialBindingKind),
|
|
496
|
+
status: CredentialBindingResolutionStatus
|
|
497
|
+
});
|
|
498
|
+
var credentialBindingId = (input) => CredentialBindingId.make(
|
|
499
|
+
JSON.stringify([input.pluginId, input.sourceScope, input.sourceId, input.slotKey])
|
|
500
|
+
);
|
|
501
|
+
var credentialSlotPart = (value) => value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "default";
|
|
502
|
+
var credentialSlotKey = (prefix, name) => `${prefix}:${credentialSlotPart(name)}`;
|
|
503
|
+
var credentialBindingValueFromRow = (row) => Match.value(row).pipe(
|
|
504
|
+
Match.when({ kind: "text" }, ({ text_value }) => ({
|
|
505
|
+
kind: "text",
|
|
506
|
+
text: text_value
|
|
507
|
+
})),
|
|
508
|
+
Match.when({ kind: "secret" }, ({ scope_id, secret_id, secret_scope_id }) => ({
|
|
509
|
+
kind: "secret",
|
|
510
|
+
secretId: SecretId.make(secret_id),
|
|
511
|
+
secretScopeId: ScopeId.make(secret_scope_id ?? scope_id)
|
|
512
|
+
})),
|
|
513
|
+
Match.when({ kind: "connection" }, ({ connection_id }) => ({
|
|
514
|
+
kind: "connection",
|
|
515
|
+
connectionId: ConnectionId.make(connection_id)
|
|
516
|
+
})),
|
|
517
|
+
Match.exhaustive
|
|
518
|
+
);
|
|
519
|
+
var credentialBindingRowToRef = (row) => {
|
|
520
|
+
const value = credentialBindingValueFromRow(row);
|
|
521
|
+
return CredentialBindingRef.make({
|
|
522
|
+
id: CredentialBindingId.make(row.id),
|
|
523
|
+
scopeId: ScopeId.make(row.scope_id),
|
|
524
|
+
pluginId: row.plugin_id,
|
|
525
|
+
sourceId: row.source_id,
|
|
526
|
+
sourceScopeId: ScopeId.make(row.source_scope_id),
|
|
527
|
+
slotKey: row.slot_key,
|
|
528
|
+
value,
|
|
529
|
+
createdAt: row.created_at instanceof Date ? row.created_at : new Date(row.created_at),
|
|
530
|
+
updatedAt: row.updated_at instanceof Date ? row.updated_at : new Date(row.updated_at)
|
|
531
|
+
});
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
// src/oauth.ts
|
|
535
|
+
import { Effect as Effect3, Schema as Schema3 } from "effect";
|
|
536
|
+
var OAuthDynamicDcrStrategy = Schema3.Struct({
|
|
537
|
+
kind: Schema3.Literal("dynamic-dcr"),
|
|
538
|
+
/** Scopes to request. Defaults to whatever `scopes_supported`
|
|
539
|
+
* advertises; caller can narrow or extend. */
|
|
540
|
+
scopes: Schema3.optional(Schema3.Array(Schema3.String))
|
|
541
|
+
});
|
|
542
|
+
var OAuthAuthorizationCodeStrategy = Schema3.Struct({
|
|
543
|
+
kind: Schema3.Literal("authorization-code"),
|
|
544
|
+
authorizationEndpoint: Schema3.String,
|
|
545
|
+
tokenEndpoint: Schema3.String,
|
|
546
|
+
/** Expected authorization-server issuer for ID token validation. Some
|
|
547
|
+
* providers use a token endpoint host that differs from issuer, or a
|
|
548
|
+
* path-scoped issuer such as Okta custom authorization servers. */
|
|
549
|
+
issuerUrl: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
550
|
+
/** Secret id holding the `client_id`. Using a secret row rather than
|
|
551
|
+
* an inline string so the value lives at the scope where the caller
|
|
552
|
+
* configured it and shadowing behaves consistently. */
|
|
553
|
+
clientIdSecretId: Schema3.String,
|
|
554
|
+
clientIdSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
555
|
+
/** Secret id for `client_secret`. Null for public clients using
|
|
556
|
+
* PKCE without a confidential secret. */
|
|
557
|
+
clientSecretSecretId: Schema3.NullOr(Schema3.String),
|
|
558
|
+
clientSecretSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
559
|
+
scopes: Schema3.Array(Schema3.String),
|
|
560
|
+
/** Separator between scopes. RFC 6749 says space; some providers
|
|
561
|
+
* (GitHub classic) use comma. */
|
|
562
|
+
scopeSeparator: Schema3.optional(Schema3.String),
|
|
563
|
+
/** Provider-specific params injected at authorization URL build time
|
|
564
|
+
* (Google's `access_type=offline`, `prompt=consent`, ...). */
|
|
565
|
+
extraAuthorizationParams: Schema3.optional(Schema3.Record(Schema3.String, Schema3.String)),
|
|
566
|
+
/** `"body"` (default) sends client creds in the form body; `"basic"`
|
|
567
|
+
* uses HTTP Basic auth. Stripe-style servers require basic. */
|
|
568
|
+
clientAuth: Schema3.optional(Schema3.Literals(["body", "basic"]))
|
|
569
|
+
});
|
|
570
|
+
var OAuthClientCredentialsStrategy = Schema3.Struct({
|
|
571
|
+
kind: Schema3.Literal("client-credentials"),
|
|
572
|
+
tokenEndpoint: Schema3.String,
|
|
573
|
+
clientIdSecretId: Schema3.String,
|
|
574
|
+
clientIdSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
575
|
+
clientSecretSecretId: Schema3.String,
|
|
576
|
+
clientSecretSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
577
|
+
scopes: Schema3.optional(Schema3.Array(Schema3.String)),
|
|
578
|
+
scopeSeparator: Schema3.optional(Schema3.String),
|
|
579
|
+
clientAuth: Schema3.optional(Schema3.Literals(["body", "basic"]))
|
|
580
|
+
});
|
|
581
|
+
var OAuthStrategy = Schema3.Union([
|
|
582
|
+
OAuthDynamicDcrStrategy,
|
|
583
|
+
OAuthAuthorizationCodeStrategy,
|
|
584
|
+
OAuthClientCredentialsStrategy
|
|
585
|
+
]);
|
|
586
|
+
var OAuthProviderState = Schema3.Union([
|
|
587
|
+
Schema3.Struct({
|
|
588
|
+
kind: Schema3.Literal("dynamic-dcr"),
|
|
589
|
+
tokenEndpoint: Schema3.String,
|
|
590
|
+
issuerUrl: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
591
|
+
authorizationServerUrl: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
592
|
+
authorizationServerMetadataUrl: Schema3.NullOr(Schema3.String),
|
|
593
|
+
idTokenSigningAlgValuesSupported: Schema3.optional(Schema3.Array(Schema3.String)),
|
|
594
|
+
/** DCR-minted client_id. Embedded inline (not a secret) — DCR
|
|
595
|
+
* clients are public-ish by design; the secret part (if the AS
|
|
596
|
+
* issued one) is a separate secret row. */
|
|
597
|
+
clientId: Schema3.String,
|
|
598
|
+
clientSecretSecretId: Schema3.NullOr(Schema3.String),
|
|
599
|
+
clientSecretSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
600
|
+
clientAuth: Schema3.Literals(["body", "basic"]),
|
|
601
|
+
scopes: Schema3.Array(Schema3.String).pipe(Schema3.withDecodingDefaultType(Effect3.succeed([]))),
|
|
602
|
+
scopeSeparator: Schema3.optional(Schema3.String),
|
|
603
|
+
scope: Schema3.NullOr(Schema3.String),
|
|
604
|
+
/** RFC 8707 canonical resource URL. Replayed on refresh so the new
|
|
605
|
+
* access token's audience stays bound to the same resource. */
|
|
606
|
+
resource: Schema3.optional(Schema3.NullOr(Schema3.String))
|
|
607
|
+
}),
|
|
608
|
+
Schema3.Struct({
|
|
609
|
+
kind: Schema3.Literal("authorization-code"),
|
|
610
|
+
tokenEndpoint: Schema3.String,
|
|
611
|
+
issuerUrl: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
612
|
+
clientIdSecretId: Schema3.String,
|
|
613
|
+
clientIdSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
614
|
+
clientSecretSecretId: Schema3.NullOr(Schema3.String),
|
|
615
|
+
clientSecretSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
616
|
+
clientAuth: Schema3.Literals(["body", "basic"]),
|
|
617
|
+
scopes: Schema3.Array(Schema3.String).pipe(Schema3.withDecodingDefaultType(Effect3.succeed([]))),
|
|
618
|
+
scopeSeparator: Schema3.optional(Schema3.String),
|
|
619
|
+
scope: Schema3.NullOr(Schema3.String),
|
|
620
|
+
resource: Schema3.optional(Schema3.NullOr(Schema3.String))
|
|
621
|
+
}),
|
|
622
|
+
Schema3.Struct({
|
|
623
|
+
kind: Schema3.Literal("client-credentials"),
|
|
624
|
+
tokenEndpoint: Schema3.String,
|
|
625
|
+
clientIdSecretId: Schema3.String,
|
|
626
|
+
clientIdSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
627
|
+
clientSecretSecretId: Schema3.String,
|
|
628
|
+
clientSecretSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
629
|
+
scopes: Schema3.Array(Schema3.String),
|
|
630
|
+
scopeSeparator: Schema3.optional(Schema3.String),
|
|
631
|
+
clientAuth: Schema3.Literals(["body", "basic"]),
|
|
632
|
+
scope: Schema3.NullOr(Schema3.String)
|
|
633
|
+
})
|
|
634
|
+
]);
|
|
635
|
+
var OAUTH2_PROVIDER_KEY = "oauth2";
|
|
636
|
+
var OAuthProbeError = class extends Schema3.TaggedErrorClass()(
|
|
637
|
+
"OAuthProbeError",
|
|
638
|
+
{
|
|
639
|
+
message: Schema3.String
|
|
640
|
+
},
|
|
641
|
+
{ httpApiStatus: 400 }
|
|
642
|
+
) {
|
|
643
|
+
};
|
|
644
|
+
var OAuthStartError = class extends Schema3.TaggedErrorClass()(
|
|
645
|
+
"OAuthStartError",
|
|
646
|
+
{
|
|
647
|
+
message: Schema3.String,
|
|
648
|
+
/** RFC 6749 §5.2 / RFC 7591 §3.2.2 error code propagated up from the
|
|
649
|
+
* authorization server (e.g. `invalid_client_metadata`). UI surfaces
|
|
650
|
+
* it as the structured "AS rejected the registration" reason. */
|
|
651
|
+
error: Schema3.optional(Schema3.String),
|
|
652
|
+
errorDescription: Schema3.optional(Schema3.String)
|
|
653
|
+
},
|
|
654
|
+
{ httpApiStatus: 400 }
|
|
655
|
+
) {
|
|
656
|
+
};
|
|
657
|
+
var OAuthCompleteError = class extends Schema3.TaggedErrorClass()(
|
|
658
|
+
"OAuthCompleteError",
|
|
659
|
+
{
|
|
660
|
+
message: Schema3.String,
|
|
661
|
+
/** RFC 6749 §5.2 error code, when the token endpoint returned one.
|
|
662
|
+
* Callers distinguish terminal failures (`invalid_grant` ⇒
|
|
663
|
+
* re-auth required) from transient ones. */
|
|
664
|
+
code: Schema3.optional(Schema3.String)
|
|
665
|
+
},
|
|
666
|
+
{ httpApiStatus: 400 }
|
|
667
|
+
) {
|
|
668
|
+
};
|
|
669
|
+
var OAuthSessionNotFoundError = class extends Schema3.TaggedErrorClass()(
|
|
670
|
+
"OAuthSessionNotFoundError",
|
|
671
|
+
{
|
|
672
|
+
sessionId: Schema3.String
|
|
673
|
+
},
|
|
674
|
+
{ httpApiStatus: 404 }
|
|
675
|
+
) {
|
|
676
|
+
};
|
|
677
|
+
var OAUTH2_SESSION_TTL_MS = 15 * 60 * 1e3;
|
|
678
|
+
|
|
679
|
+
// src/policies.ts
|
|
680
|
+
import { Match as Match2, Schema as Schema4 } from "effect";
|
|
681
|
+
var matchPattern = (pattern, toolId) => {
|
|
682
|
+
if (pattern === "*") return true;
|
|
683
|
+
if (pattern === toolId) return true;
|
|
684
|
+
if (pattern.endsWith(".*")) {
|
|
685
|
+
const prefix = pattern.slice(0, -2);
|
|
686
|
+
if (prefix.length === 0) return false;
|
|
687
|
+
return toolId === prefix || toolId.startsWith(`${prefix}.`);
|
|
688
|
+
}
|
|
689
|
+
return false;
|
|
690
|
+
};
|
|
691
|
+
var isValidPattern = (pattern) => {
|
|
692
|
+
if (pattern.length === 0) return false;
|
|
693
|
+
if (pattern === "*") return true;
|
|
694
|
+
if (pattern.startsWith(".") || pattern.endsWith(".")) return false;
|
|
695
|
+
if (pattern.includes("..")) return false;
|
|
696
|
+
if (pattern.startsWith("*")) return false;
|
|
697
|
+
const segments = pattern.split(".");
|
|
698
|
+
for (let i = 0; i < segments.length; i++) {
|
|
699
|
+
const seg = segments[i];
|
|
700
|
+
if (seg.length === 0) return false;
|
|
701
|
+
if (seg.includes("*") && seg !== "*") return false;
|
|
702
|
+
if (seg === "*" && i !== segments.length - 1) return false;
|
|
703
|
+
}
|
|
704
|
+
return true;
|
|
705
|
+
};
|
|
706
|
+
var comparePolicyRow = (a, b) => {
|
|
707
|
+
const pa = a.position;
|
|
708
|
+
const pb = b.position;
|
|
709
|
+
if (pa < pb) return -1;
|
|
710
|
+
if (pa > pb) return 1;
|
|
711
|
+
const ia = a.id;
|
|
712
|
+
const ib = b.id;
|
|
713
|
+
return ia < ib ? -1 : ia > ib ? 1 : 0;
|
|
714
|
+
};
|
|
715
|
+
var actionRestrictionRank = (action) => Match2.value(action).pipe(
|
|
716
|
+
Match2.when("block", () => 3),
|
|
717
|
+
Match2.when("require_approval", () => 2),
|
|
718
|
+
Match2.when("approve", () => 1),
|
|
719
|
+
Match2.exhaustive
|
|
720
|
+
);
|
|
721
|
+
var moreRestrictive = (current, candidate) => {
|
|
722
|
+
if (!current) return candidate;
|
|
723
|
+
const currentRank = actionRestrictionRank(current.action);
|
|
724
|
+
const candidateRank = actionRestrictionRank(candidate.action);
|
|
725
|
+
return candidateRank > currentRank ? candidate : current;
|
|
726
|
+
};
|
|
727
|
+
var resolveToolPolicy = (toolId, policies, scopeRank) => {
|
|
728
|
+
if (policies.length === 0) return void 0;
|
|
729
|
+
const sorted = [...policies].sort((a, b) => {
|
|
730
|
+
const sa = scopeRank(a);
|
|
731
|
+
const sb = scopeRank(b);
|
|
732
|
+
if (sa !== sb) return sa - sb;
|
|
733
|
+
return comparePolicyRow(a, b);
|
|
734
|
+
});
|
|
735
|
+
const firstMatchByScope = /* @__PURE__ */ new Map();
|
|
736
|
+
for (const row of sorted) {
|
|
737
|
+
if (firstMatchByScope.has(row.scope_id)) continue;
|
|
738
|
+
if (matchPattern(row.pattern, toolId)) {
|
|
739
|
+
firstMatchByScope.set(row.scope_id, {
|
|
740
|
+
action: row.action,
|
|
741
|
+
pattern: row.pattern,
|
|
742
|
+
policyId: row.id
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
let selected;
|
|
747
|
+
for (const match of firstMatchByScope.values()) {
|
|
748
|
+
selected = moreRestrictive(selected, match);
|
|
749
|
+
}
|
|
750
|
+
return selected;
|
|
751
|
+
};
|
|
752
|
+
var liftPlugin = (defaultRequiresApproval) => defaultRequiresApproval ? { action: "require_approval", source: "plugin-default" } : { action: "approve", source: "plugin-default" };
|
|
753
|
+
var liftUser = (match) => ({
|
|
754
|
+
action: match.action,
|
|
755
|
+
source: "user",
|
|
756
|
+
pattern: match.pattern,
|
|
757
|
+
policyId: match.policyId
|
|
758
|
+
});
|
|
759
|
+
var resolveEffectivePolicy = (toolId, policies, scopeRank, defaultRequiresApproval) => {
|
|
760
|
+
const match = resolveToolPolicy(toolId, policies, scopeRank);
|
|
761
|
+
return match ? liftUser(match) : liftPlugin(defaultRequiresApproval);
|
|
762
|
+
};
|
|
763
|
+
var effectivePolicyFromSorted = (toolId, sortedPolicies, defaultRequiresApproval) => {
|
|
764
|
+
const firstMatchByScope = /* @__PURE__ */ new Map();
|
|
765
|
+
for (const p of sortedPolicies) {
|
|
766
|
+
const scopeKey = "scopeId" in p && p.scopeId ? String(p.scopeId) : "__flat__";
|
|
767
|
+
if (firstMatchByScope.has(scopeKey)) continue;
|
|
768
|
+
if (matchPattern(p.pattern, toolId)) {
|
|
769
|
+
firstMatchByScope.set(scopeKey, {
|
|
770
|
+
action: p.action,
|
|
771
|
+
source: "user",
|
|
772
|
+
pattern: p.pattern,
|
|
773
|
+
policyId: p.id
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
let selected;
|
|
778
|
+
for (const match of firstMatchByScope.values()) {
|
|
779
|
+
selected = moreRestrictive(selected, match);
|
|
780
|
+
}
|
|
781
|
+
return selected ?? liftPlugin(defaultRequiresApproval);
|
|
782
|
+
};
|
|
783
|
+
var rowToToolPolicy = (row) => ({
|
|
784
|
+
id: PolicyId.make(row.id),
|
|
785
|
+
scopeId: ScopeId.make(row.scope_id),
|
|
786
|
+
pattern: row.pattern,
|
|
787
|
+
action: row.action,
|
|
788
|
+
position: row.position,
|
|
789
|
+
createdAt: row.created_at,
|
|
790
|
+
updatedAt: row.updated_at
|
|
791
|
+
});
|
|
792
|
+
var ToolPolicyActionSchema = Schema4.Literals(["approve", "require_approval", "block"]);
|
|
793
|
+
|
|
794
|
+
// src/types.ts
|
|
795
|
+
import { Schema as Schema5 } from "effect";
|
|
796
|
+
var ToolSchema = Schema5.Struct({
|
|
797
|
+
id: ToolId,
|
|
798
|
+
name: Schema5.optional(Schema5.String),
|
|
799
|
+
description: Schema5.optional(Schema5.String),
|
|
800
|
+
inputSchema: Schema5.optional(Schema5.Unknown),
|
|
801
|
+
outputSchema: Schema5.optional(Schema5.Unknown),
|
|
802
|
+
schemaDefinitions: Schema5.optional(Schema5.Record(Schema5.String, Schema5.Unknown)),
|
|
803
|
+
inputTypeScript: Schema5.optional(Schema5.String),
|
|
804
|
+
outputTypeScript: Schema5.optional(Schema5.String),
|
|
805
|
+
typeScriptDefinitions: Schema5.optional(Schema5.Record(Schema5.String, Schema5.String))
|
|
806
|
+
});
|
|
807
|
+
var SourceDetectionResult = Schema5.Struct({
|
|
808
|
+
/** Plugin id that recognized the URL (e.g. "openapi", "graphql"). */
|
|
809
|
+
kind: Schema5.String,
|
|
810
|
+
/** Confidence tier — UI uses this to pick a winner when multiple
|
|
811
|
+
* plugins claim a URL. */
|
|
812
|
+
confidence: Schema5.Literals(["high", "medium", "low"]),
|
|
813
|
+
/** The (possibly normalized) endpoint the plugin will use. */
|
|
814
|
+
endpoint: Schema5.String,
|
|
815
|
+
/** Human-readable name suggestion, typically derived from spec title
|
|
816
|
+
* or URL hostname. */
|
|
817
|
+
name: Schema5.String,
|
|
818
|
+
/** Namespace suggestion — the plugin's recommendation for the source
|
|
819
|
+
* id. UI may override. */
|
|
820
|
+
namespace: Schema5.String
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
// src/usages.ts
|
|
824
|
+
import { Schema as Schema6 } from "effect";
|
|
825
|
+
var Usage = Schema6.Struct({
|
|
826
|
+
pluginId: Schema6.String,
|
|
827
|
+
scopeId: ScopeId,
|
|
828
|
+
ownerKind: Schema6.String,
|
|
829
|
+
ownerId: Schema6.String,
|
|
830
|
+
ownerName: Schema6.NullOr(Schema6.String),
|
|
831
|
+
slot: Schema6.String
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
// src/errors.ts
|
|
835
|
+
import { Data as Data2, Schema as Schema7 } from "effect";
|
|
836
|
+
var ToolNotFoundError = class extends Schema7.TaggedErrorClass()(
|
|
837
|
+
"ToolNotFoundError",
|
|
838
|
+
{
|
|
839
|
+
toolId: ToolId,
|
|
840
|
+
suggestions: Schema7.optional(Schema7.Array(ToolId))
|
|
841
|
+
}
|
|
842
|
+
) {
|
|
843
|
+
};
|
|
844
|
+
var ToolInvocationError = class extends Data2.TaggedError("ToolInvocationError") {
|
|
845
|
+
};
|
|
846
|
+
var PluginNotLoadedError = class extends Schema7.TaggedErrorClass()(
|
|
847
|
+
"PluginNotLoadedError",
|
|
848
|
+
{
|
|
849
|
+
pluginId: Schema7.String,
|
|
850
|
+
toolId: ToolId
|
|
851
|
+
}
|
|
852
|
+
) {
|
|
853
|
+
};
|
|
854
|
+
var NoHandlerError = class extends Schema7.TaggedErrorClass()("NoHandlerError", {
|
|
855
|
+
toolId: ToolId,
|
|
856
|
+
pluginId: Schema7.String
|
|
857
|
+
}) {
|
|
858
|
+
};
|
|
859
|
+
var ToolBlockedError = class extends Schema7.TaggedErrorClass()(
|
|
860
|
+
"ToolBlockedError",
|
|
861
|
+
{
|
|
862
|
+
toolId: ToolId,
|
|
863
|
+
pattern: Schema7.String
|
|
864
|
+
}
|
|
865
|
+
) {
|
|
866
|
+
};
|
|
867
|
+
var SourceNotFoundError = class extends Schema7.TaggedErrorClass()(
|
|
868
|
+
"SourceNotFoundError",
|
|
869
|
+
{ sourceId: Schema7.String }
|
|
870
|
+
) {
|
|
871
|
+
};
|
|
872
|
+
var SourceRemovalNotAllowedError = class extends Schema7.TaggedErrorClass()(
|
|
873
|
+
"SourceRemovalNotAllowedError",
|
|
874
|
+
{ sourceId: Schema7.String }
|
|
875
|
+
) {
|
|
876
|
+
};
|
|
877
|
+
var SecretNotFoundError = class extends Schema7.TaggedErrorClass()(
|
|
878
|
+
"SecretNotFoundError",
|
|
879
|
+
{ secretId: SecretId }
|
|
880
|
+
) {
|
|
881
|
+
};
|
|
882
|
+
var SecretResolutionError = class extends Schema7.TaggedErrorClass()(
|
|
883
|
+
"SecretResolutionError",
|
|
884
|
+
{
|
|
885
|
+
secretId: SecretId,
|
|
886
|
+
message: Schema7.String
|
|
887
|
+
}
|
|
888
|
+
) {
|
|
889
|
+
};
|
|
890
|
+
var SecretOwnedByConnectionError = class extends Schema7.TaggedErrorClass()(
|
|
891
|
+
"SecretOwnedByConnectionError",
|
|
892
|
+
{
|
|
893
|
+
secretId: SecretId,
|
|
894
|
+
connectionId: ConnectionId
|
|
895
|
+
}
|
|
896
|
+
) {
|
|
897
|
+
};
|
|
898
|
+
var SecretInUseError = class extends Schema7.TaggedErrorClass()(
|
|
899
|
+
"SecretInUseError",
|
|
900
|
+
{
|
|
901
|
+
secretId: SecretId,
|
|
902
|
+
usageCount: Schema7.Number
|
|
903
|
+
}
|
|
904
|
+
) {
|
|
905
|
+
};
|
|
906
|
+
var ConnectionNotFoundError = class extends Schema7.TaggedErrorClass()(
|
|
907
|
+
"ConnectionNotFoundError",
|
|
908
|
+
{ connectionId: ConnectionId }
|
|
909
|
+
) {
|
|
910
|
+
};
|
|
911
|
+
var ConnectionProviderNotRegisteredError = class extends Schema7.TaggedErrorClass()(
|
|
912
|
+
"ConnectionProviderNotRegisteredError",
|
|
913
|
+
{
|
|
914
|
+
provider: Schema7.String,
|
|
915
|
+
connectionId: Schema7.optional(ConnectionId)
|
|
916
|
+
}
|
|
917
|
+
) {
|
|
918
|
+
};
|
|
919
|
+
var ConnectionRefreshNotSupportedError = class extends Schema7.TaggedErrorClass()(
|
|
920
|
+
"ConnectionRefreshNotSupportedError",
|
|
921
|
+
{
|
|
922
|
+
connectionId: ConnectionId,
|
|
923
|
+
provider: Schema7.String
|
|
924
|
+
}
|
|
925
|
+
) {
|
|
926
|
+
};
|
|
927
|
+
var ConnectionReauthRequiredError = class extends Schema7.TaggedErrorClass()(
|
|
928
|
+
"ConnectionReauthRequiredError",
|
|
929
|
+
{
|
|
930
|
+
connectionId: ConnectionId,
|
|
931
|
+
provider: Schema7.String,
|
|
932
|
+
message: Schema7.String
|
|
933
|
+
}
|
|
934
|
+
) {
|
|
935
|
+
};
|
|
936
|
+
var ConnectionInUseError = class extends Schema7.TaggedErrorClass()(
|
|
937
|
+
"ConnectionInUseError",
|
|
938
|
+
{
|
|
939
|
+
connectionId: ConnectionId,
|
|
940
|
+
usageCount: Schema7.Number
|
|
941
|
+
}
|
|
942
|
+
) {
|
|
943
|
+
};
|
|
944
|
+
|
|
945
|
+
// src/plugin-storage.ts
|
|
946
|
+
var pluginStorageId = (input) => JSON.stringify([input.pluginId, input.collection, input.key]);
|
|
947
|
+
|
|
948
|
+
export {
|
|
949
|
+
StorageError,
|
|
950
|
+
UniqueViolationError,
|
|
951
|
+
isStorageFailure,
|
|
952
|
+
makeFumaClient,
|
|
953
|
+
ScopeId,
|
|
954
|
+
ToolId,
|
|
955
|
+
SecretId,
|
|
956
|
+
PolicyId,
|
|
957
|
+
ConnectionId,
|
|
958
|
+
CredentialBindingId,
|
|
959
|
+
assertExecutorScopePolicyTable,
|
|
960
|
+
textColumn,
|
|
961
|
+
nullableTextColumn,
|
|
962
|
+
boolColumn,
|
|
963
|
+
bigintColumn,
|
|
964
|
+
nullableBigintColumn,
|
|
965
|
+
jsonColumn,
|
|
966
|
+
nullableJsonColumn,
|
|
967
|
+
dateColumn,
|
|
968
|
+
scopedExecutorTable,
|
|
969
|
+
coreSchema,
|
|
970
|
+
TOOL_POLICY_ACTIONS,
|
|
971
|
+
isToolPolicyAction,
|
|
972
|
+
CredentialBindingKind,
|
|
973
|
+
CredentialBindingValue,
|
|
974
|
+
ConfiguredCredentialBinding,
|
|
975
|
+
ConfiguredCredentialValue,
|
|
976
|
+
ScopedSecretCredentialInput,
|
|
977
|
+
CredentialBindingRef,
|
|
978
|
+
CredentialBindingSlotInput,
|
|
979
|
+
RemoveCredentialBindingInput,
|
|
980
|
+
ReplaceCredentialBindingValue,
|
|
981
|
+
ReplaceCredentialBindingsInput,
|
|
982
|
+
SourceCredentialBindingSource,
|
|
983
|
+
SourceCredentialBindingSourceInput,
|
|
984
|
+
SourceCredentialBindingSlotInput,
|
|
985
|
+
SetSourceCredentialBindingInput,
|
|
986
|
+
RemoveSourceCredentialBindingInput,
|
|
987
|
+
ReplaceSourceCredentialBindingsInput,
|
|
988
|
+
CredentialBindingResolutionStatus,
|
|
989
|
+
ResolvedCredentialSlot,
|
|
990
|
+
credentialBindingId,
|
|
991
|
+
credentialSlotPart,
|
|
992
|
+
credentialSlotKey,
|
|
993
|
+
credentialBindingValueFromRow,
|
|
994
|
+
credentialBindingRowToRef,
|
|
995
|
+
OAuthDynamicDcrStrategy,
|
|
996
|
+
OAuthAuthorizationCodeStrategy,
|
|
997
|
+
OAuthClientCredentialsStrategy,
|
|
998
|
+
OAuthStrategy,
|
|
999
|
+
OAuthProviderState,
|
|
1000
|
+
OAUTH2_PROVIDER_KEY,
|
|
1001
|
+
OAuthProbeError,
|
|
1002
|
+
OAuthStartError,
|
|
1003
|
+
OAuthCompleteError,
|
|
1004
|
+
OAuthSessionNotFoundError,
|
|
1005
|
+
OAUTH2_SESSION_TTL_MS,
|
|
1006
|
+
matchPattern,
|
|
1007
|
+
isValidPattern,
|
|
1008
|
+
comparePolicyRow,
|
|
1009
|
+
resolveToolPolicy,
|
|
1010
|
+
resolveEffectivePolicy,
|
|
1011
|
+
effectivePolicyFromSorted,
|
|
1012
|
+
rowToToolPolicy,
|
|
1013
|
+
ToolPolicyActionSchema,
|
|
1014
|
+
ToolSchema,
|
|
1015
|
+
SourceDetectionResult,
|
|
1016
|
+
Usage,
|
|
1017
|
+
ToolNotFoundError,
|
|
1018
|
+
ToolInvocationError,
|
|
1019
|
+
PluginNotLoadedError,
|
|
1020
|
+
NoHandlerError,
|
|
1021
|
+
ToolBlockedError,
|
|
1022
|
+
SourceNotFoundError,
|
|
1023
|
+
SourceRemovalNotAllowedError,
|
|
1024
|
+
SecretNotFoundError,
|
|
1025
|
+
SecretResolutionError,
|
|
1026
|
+
SecretOwnedByConnectionError,
|
|
1027
|
+
SecretInUseError,
|
|
1028
|
+
ConnectionNotFoundError,
|
|
1029
|
+
ConnectionProviderNotRegisteredError,
|
|
1030
|
+
ConnectionRefreshNotSupportedError,
|
|
1031
|
+
ConnectionReauthRequiredError,
|
|
1032
|
+
ConnectionInUseError,
|
|
1033
|
+
pluginStorageId
|
|
1034
|
+
};
|
|
1035
|
+
//# sourceMappingURL=chunk-ZANQD7E2.js.map
|