// src/fuma-runtime.ts
import { Cause, Context, Data, Effect, Exit, Layer, Predicate } from "effect";
var StorageError = class extends Data.TaggedError("StorageError") {
};
var UniqueViolationError = class extends Data.TaggedError("UniqueViolationError") {
};
var isUniqueViolation = (cause) => {
  let current = cause;
  for (let i = 0; i < 5; i += 1) {
    const err = current && typeof current === "object" ? current : null;
    if (!err) return false;
    const code = err["code"];
    const message = err["message"];
    const innerCause = err["cause"];
    if (code === "23505") return true;
    if (typeof message === "string" && /unique constraint|duplicate key|violates unique constraint/i.test(message)) {
      return true;
    }
    if (!innerCause || innerCause === current) return false;
    current = innerCause;
  }
  return false;
};
var causeMessage = (cause) => {
  const message = cause && typeof cause === "object" ? (
    // oxlint-disable-next-line executor/no-unknown-error-message -- boundary: preserve database driver error text inside typed StorageError
    cause["message"]
  ) : void 0;
  return typeof message === "string" && message.length > 0 ? message : void 0;
};
var isStorageFailure = (error) => Predicate.isTagged(error, "StorageError") || Predicate.isTagged(error, "UniqueViolationError");
var fumaFailureFromCause = (label, cause) => {
  if (isStorageFailure(cause)) return cause;
  if (isUniqueViolation(cause)) return new UniqueViolationError({ model: label });
  return new StorageError({
    message: causeMessage(cause) ?? `FumaDB operation failed: ${label}`,
    cause
  });
};
var fumaEffect = (label, run) => Effect.tryPromise({
  try: run,
  catch: (cause) => fumaFailureFromCause(label, cause)
});
var activeFumaDbRef = Context.Reference("executor/ActiveFumaDb", {
  defaultValue: () => null
});
var TransactionEffectFailure = class {
  constructor(error) {
    this.error = error;
  }
  error;
};
var TransactionEffectDefect = class {
  constructor(cause) {
    this.cause = cause;
  }
  cause;
};
var isAllowedTable = (tables, table2) => tables === void 0 || typeof table2 === "string" && tables.has(table2);
var assertAllowedTable = (tables, table2) => {
  if (isAllowedTable(tables, table2)) return;
  throw new StorageError({
    message: `FumaDB table "${String(table2)}" is not available through this storage boundary.`,
    cause: void 0
  });
};
var makeSafeFumaQuery = (db, options) => {
  const table2 = (name) => {
    assertAllowedTable(options.tables, name);
    return name;
  };
  const query = {
    count: (name, value) => db.count(table2(name), value),
    create: (name, value) => db.create(table2(name), value),
    createMany: (name, values) => db.createMany(table2(name), values),
    deleteMany: (name, value) => db.deleteMany(table2(name), value),
    findFirst: (name, value) => db.findFirst(table2(name), value),
    findMany: (name, value) => db.findMany(table2(name), value),
    transaction: (run) => db.transaction((transactionDb) => run(makeSafeFumaQuery(transactionDb, options))),
    updateMany: (name, value) => db.updateMany(table2(name), value),
    upsert: (name, value) => db.upsert(table2(name), value)
  };
  return Object.freeze(query);
};
var makeFumaClient = (db, options = {}) => {
  const use = (label, fn) => Effect.flatMap(
    Effect.service(activeFumaDbRef),
    (active) => fumaEffect(label, () => fn(makeSafeFumaQuery(active ?? db, options)))
  ).pipe(Effect.withSpan(`fumadb.${label}`));
  const transaction = (effect) => Effect.flatMap(Effect.service(activeFumaDbRef), (active) => {
    if (active) return effect;
    return Effect.tryPromise({
      try: () => db.transaction(async (transactionDb) => {
        const exit = await Effect.runPromiseExit(
          effect.pipe(Effect.provideService(activeFumaDbRef, transactionDb))
        );
        if (Exit.isSuccess(exit)) return exit.value;
        const failure = exit.cause.reasons.find(Cause.isFailReason);
        if (failure) throw new TransactionEffectFailure(failure.error);
        throw new TransactionEffectDefect(exit.cause);
      }),
      catch: (cause) => {
        if (cause instanceof TransactionEffectFailure) return cause.error;
        if (cause instanceof TransactionEffectDefect) {
          return fumaFailureFromCause("transaction", cause.cause);
        }
        return fumaFailureFromCause("transaction", cause);
      }
    });
  }).pipe(Effect.withSpan("fumadb.transaction"));
  return { use, transaction };
};
var FumaClient = class extends Context.Service()("executor/FumaClient") {
  static layer = (db) => Layer.succeed(this)(makeFumaClient(db));
};

// src/ids.ts
import { Schema } from "effect";
var ScopeId = Schema.String.pipe(Schema.brand("ScopeId"));
var ToolId = Schema.String.pipe(Schema.brand("ToolId"));
var SecretId = Schema.String.pipe(Schema.brand("SecretId"));
var PolicyId = Schema.String.pipe(Schema.brand("PolicyId"));
var ConnectionId = Schema.String.pipe(Schema.brand("ConnectionId"));
var CredentialBindingId = Schema.String.pipe(Schema.brand("CredentialBindingId"));

// src/core-schema.ts
import { column, idColumn, table } from "fumadb/schema";

// src/scope-policy.ts
import { ConditionType } from "fumadb/query";
var executorScopePolicyName = "executor.scope";
var executorUnscopedPolicyName = "executor.unscoped";
var unscopedExecutorTables = /* @__PURE__ */ new Set(["blob"]);
var scopePolicyViolation = (message) => {
  throw new StorageError({ message, cause: void 0 });
};
function assertExecutorScopePolicyTable(table2, tableKey) {
  const tableName = table2.ormName || tableKey || table2.names.sql;
  const scopedPolicy = table2.policies.find((policy) => policy.name === executorScopePolicyName);
  if (scopedPolicy?.onRead && scopedPolicy.onCreate && scopedPolicy.onUpdate && scopedPolicy.onDelete) {
    return;
  }
  const unscopedPolicy = table2.policies.find(
    (policy) => policy.name === executorUnscopedPolicyName
  );
  if (unscopedPolicy && unscopedExecutorTables.has(tableName)) return;
  scopePolicyViolation(`Storage table "${tableName}" is missing an executor scope policy.`);
}
var requireExecutorScopeContext = (tableName, access, context) => {
  if (context) return context;
  return scopePolicyViolation(
    `Storage ${access} on table "${tableName}" is missing executor scope context.`
  );
};
var isExecutorScopeAllowed = (tableName, access, value, context) => {
  const scopeContext = requireExecutorScopeContext(tableName, access, context);
  return typeof value === "string" && scopeContext.allowedScopeIds.has(value);
};
var executorScopeIds = (tableName, access, context) => [...requireExecutorScopeContext(tableName, access, context).allowedScopeIds];
var findScopeTarget = (condition, columns) => {
  if (!condition) return null;
  if (condition.type === ConditionType.Compare) {
    const column2 = columns.find((name) => condition.a.ormName === name);
    if (!column2 || condition.operator !== "=" || typeof condition.b !== "string") return null;
    return { column: column2, value: condition.b };
  }
  if (condition.type !== ConditionType.And) return null;
  for (const item of condition.items) {
    const target = findScopeTarget(item, columns);
    if (target) return target;
  }
  return null;
};
var requireExecutorScopeTarget = (tableName, access, where, context, columns = ["scope_id"]) => {
  const scopeContext = requireExecutorScopeContext(tableName, access, context);
  const target = findScopeTarget(where, columns);
  if (target && scopeContext.allowedScopeIds.has(target.value)) return target;
  return scopePolicyViolation(
    `Storage ${access} on table "${tableName}" must target an explicit scope in the executor scope stack.`
  );
};
var assertExecutorScopeAllowed = (tableName, access, value, context) => {
  if (isExecutorScopeAllowed(tableName, access, value, context)) return;
  scopePolicyViolation(
    `Storage ${access} on table "${tableName}" is outside the executor scope stack.`
  );
};
var assertExecutorScopeTargetValue = (tableName, access, value, target, context) => {
  assertExecutorScopeAllowed(tableName, access, value, context);
  if (value === target.value) return;
  scopePolicyViolation(
    `Storage ${access} on table "${tableName}" must write the same scope it explicitly targets.`
  );
};

// src/core-schema.ts
var textColumn = (name) => column(name, "string");
var nullableTextColumn = (name) => column(name, "string").nullable();
var boolColumn = (name, defaultValue) => column(name, "bool").defaultTo(defaultValue);
var bigintColumn = (name) => column(name, "bigint");
var nullableBigintColumn = (name) => column(name, "bigint").nullable();
var jsonColumn = (name) => column(name, "json");
var nullableJsonColumn = (name) => column(name, "json").nullable();
var dateColumn = (name) => column(name, "timestamp");
var unscopedExecutorTable = (name, columns) => {
  const out = table(name, {
    ...columns,
    row_id: idColumn("row_id", "varchar(255)").defaultTo$("auto"),
    id: column("id", "varchar(255)")
  });
  out.unique(`${name}_id_uidx`, ["id"]);
  return out.policy({
    name: executorUnscopedPolicyName
  });
};
var scopedExecutorTableBase = (name, columns) => {
  const out = table(name, {
    ...columns,
    row_id: idColumn("row_id", "varchar(255)").defaultTo$("auto"),
    id: column("id", "varchar(255)"),
    scope_id: column("scope_id", "varchar(255)")
  });
  out.unique(`${name}_scope_id_id_uidx`, ["scope_id", "id"]);
  return out;
};
var scopedExecutorTable = (name, columns) => {
  const out = scopedExecutorTableBase(name, columns);
  return out.policy({
    name: executorScopePolicyName,
    onRead: ({ builder, context }) => builder("scope_id", "in", executorScopeIds(name, "read", context)),
    onCreate: ({ values, context }) => assertExecutorScopeAllowed(name, "write", values.scope_id, context),
    onUpdate: ({ builder, set, create, where, context }) => {
      const target = requireExecutorScopeTarget(name, "write", where, context);
      if (set.scope_id !== void 0) {
        assertExecutorScopeTargetValue(name, "write", set.scope_id, target, context);
      }
      if (create?.scope_id !== void 0) {
        assertExecutorScopeTargetValue(name, "write", create.scope_id, target, context);
      }
      return builder("scope_id", "=", target.value);
    },
    onDelete: ({ builder, where, context }) => {
      const target = requireExecutorScopeTarget(name, "delete", where, context);
      return builder("scope_id", "=", target.value);
    }
  });
};
var defineTables = (tables) => tables;
var credentialBindingKinds = ["text", "secret", "connection"];
var credentialBindingTable = (() => {
  const out = scopedExecutorTableBase("credential_binding", {
    plugin_id: textColumn("plugin_id"),
    source_id: textColumn("source_id"),
    source_scope_id: textColumn("source_scope_id"),
    slot_key: textColumn("slot_key"),
    kind: textColumn("kind"),
    text_value: nullableTextColumn("text_value"),
    secret_id: nullableTextColumn("secret_id"),
    secret_scope_id: nullableTextColumn("secret_scope_id"),
    connection_id: nullableTextColumn("connection_id"),
    created_at: dateColumn("created_at"),
    updated_at: dateColumn("updated_at")
  });
  return out.policy({
    name: executorScopePolicyName,
    onRead: ({ builder, context }) => builder("scope_id", "in", executorScopeIds("credential_binding", "read", context)),
    onCreate: ({ values, context }) => assertExecutorScopeAllowed("credential_binding", "write", values.scope_id, context),
    onUpdate: ({ builder, set, create, where, context }) => {
      const target = requireExecutorScopeTarget("credential_binding", "write", where, context);
      if (set.scope_id !== void 0) {
        assertExecutorScopeTargetValue(
          "credential_binding",
          "write",
          set.scope_id,
          target,
          context
        );
      }
      if (create?.scope_id !== void 0) {
        assertExecutorScopeTargetValue(
          "credential_binding",
          "write",
          create.scope_id,
          target,
          context
        );
      }
      return builder("scope_id", "=", target.value);
    },
    onDelete: ({ builder, where, context }) => {
      const target = requireExecutorScopeTarget("credential_binding", "delete", where, context, [
        "scope_id",
        "source_scope_id"
      ]);
      return builder(target.column, "=", target.value);
    }
  });
})();
var coreTables = defineTables({
  source: scopedExecutorTable("source", {
    plugin_id: textColumn("plugin_id"),
    kind: textColumn("kind"),
    name: textColumn("name"),
    url: nullableTextColumn("url"),
    can_remove: boolColumn("can_remove", true),
    can_refresh: boolColumn("can_refresh", false),
    can_edit: boolColumn("can_edit", false),
    created_at: dateColumn("created_at"),
    updated_at: dateColumn("updated_at")
  }),
  tool: scopedExecutorTable("tool", {
    source_id: textColumn("source_id"),
    plugin_id: textColumn("plugin_id"),
    name: textColumn("name"),
    description: textColumn("description"),
    input_schema: nullableJsonColumn("input_schema"),
    output_schema: nullableJsonColumn("output_schema"),
    created_at: dateColumn("created_at"),
    updated_at: dateColumn("updated_at")
  }),
  definition: scopedExecutorTable("definition", {
    source_id: textColumn("source_id"),
    plugin_id: textColumn("plugin_id"),
    name: textColumn("name"),
    schema: jsonColumn("schema"),
    created_at: dateColumn("created_at")
  }),
  secret: scopedExecutorTable("secret", {
    name: textColumn("name"),
    provider: textColumn("provider"),
    owned_by_connection_id: nullableTextColumn("owned_by_connection_id"),
    created_at: dateColumn("created_at")
  }),
  connection: scopedExecutorTable("connection", {
    provider: textColumn("provider"),
    identity_label: nullableTextColumn("identity_label"),
    access_token_secret_id: textColumn("access_token_secret_id"),
    refresh_token_secret_id: nullableTextColumn("refresh_token_secret_id"),
    expires_at: nullableBigintColumn("expires_at"),
    scope: nullableTextColumn("scope"),
    provider_state: nullableJsonColumn("provider_state"),
    created_at: dateColumn("created_at"),
    updated_at: dateColumn("updated_at")
  }),
  oauth2_session: scopedExecutorTable("oauth2_session", {
    plugin_id: textColumn("plugin_id"),
    strategy: textColumn("strategy"),
    connection_id: textColumn("connection_id"),
    token_scope: textColumn("token_scope"),
    redirect_url: textColumn("redirect_url"),
    payload: jsonColumn("payload"),
    expires_at: bigintColumn("expires_at"),
    created_at: dateColumn("created_at")
  }),
  credential_binding: credentialBindingTable,
  plugin_storage: scopedExecutorTable("plugin_storage", {
    plugin_id: textColumn("plugin_id"),
    collection: textColumn("collection"),
    key: textColumn("key"),
    data: jsonColumn("data"),
    created_at: dateColumn("created_at"),
    updated_at: dateColumn("updated_at")
  }),
  tool_policy: scopedExecutorTable("tool_policy", {
    pattern: textColumn("pattern"),
    action: textColumn("action"),
    position: textColumn("position"),
    created_at: dateColumn("created_at"),
    updated_at: dateColumn("updated_at")
  }),
  blob: unscopedExecutorTable("blob", {
    namespace: textColumn("namespace"),
    key: textColumn("key"),
    value: textColumn("value")
  })
});
var coreSchema = coreTables;
var TOOL_POLICY_ACTIONS = [
  "approve",
  "require_approval",
  "block"
];
var isToolPolicyAction = (value) => typeof value === "string" && TOOL_POLICY_ACTIONS.includes(value);

// src/credential-bindings.ts
import { Match, Schema as Schema2 } from "effect";
var CredentialBindingKind = Schema2.Literals(credentialBindingKinds);
var CredentialBindingValue = Schema2.Union([
  Schema2.Struct({
    kind: Schema2.Literal("text"),
    text: Schema2.String
  }),
  Schema2.Struct({
    kind: Schema2.Literal("secret"),
    secretId: SecretId,
    secretScopeId: Schema2.optional(ScopeId)
  }),
  Schema2.Struct({
    kind: Schema2.Literal("connection"),
    connectionId: ConnectionId
  })
]);
var ConfiguredCredentialBinding = Schema2.Struct({
  kind: Schema2.Literal("binding"),
  slot: Schema2.String,
  prefix: Schema2.optional(Schema2.String)
});
var ConfiguredCredentialValue = Schema2.Union([Schema2.String, ConfiguredCredentialBinding]);
var ScopedSecretCredentialInput = Schema2.Struct({
  secretId: Schema2.String,
  prefix: Schema2.optional(Schema2.String),
  targetScope: ScopeId,
  secretScopeId: Schema2.optional(ScopeId)
});
var CredentialBindingRef = Schema2.Struct({
  id: CredentialBindingId,
  scopeId: ScopeId,
  pluginId: Schema2.String,
  sourceId: Schema2.String,
  sourceScopeId: ScopeId,
  slotKey: Schema2.String,
  value: CredentialBindingValue,
  createdAt: Schema2.Date,
  updatedAt: Schema2.Date
});
var CredentialBindingSourceInput = Schema2.Struct({
  pluginId: Schema2.String,
  sourceId: Schema2.String,
  sourceScope: ScopeId
});
var CredentialBindingSlotInput = Schema2.Struct({
  pluginId: Schema2.String,
  sourceId: Schema2.String,
  sourceScope: ScopeId,
  slotKey: Schema2.String
});
var RemoveCredentialBindingInput = Schema2.Struct({
  targetScope: ScopeId,
  pluginId: Schema2.String,
  sourceId: Schema2.String,
  sourceScope: ScopeId,
  slotKey: Schema2.String
});
var ReplaceCredentialBindingValue = Schema2.Struct({
  slotKey: Schema2.String,
  value: CredentialBindingValue
});
var ReplaceCredentialBindingsInput = Schema2.Struct({
  targetScope: ScopeId,
  pluginId: Schema2.String,
  sourceId: Schema2.String,
  sourceScope: ScopeId,
  slotPrefixes: Schema2.Array(Schema2.String),
  bindings: Schema2.Array(ReplaceCredentialBindingValue)
});
var SourceCredentialBindingSource = Schema2.Struct({
  id: Schema2.String,
  scope: ScopeId
});
var SourceCredentialBindingSourceInput = Schema2.Struct({
  source: SourceCredentialBindingSource
});
var SourceCredentialBindingSlotInput = Schema2.Struct({
  source: SourceCredentialBindingSource,
  slotKey: Schema2.String
});
var SetSourceCredentialBindingInput = Schema2.Struct({
  scope: ScopeId,
  source: SourceCredentialBindingSource,
  slotKey: Schema2.String,
  value: CredentialBindingValue
});
var RemoveSourceCredentialBindingInput = Schema2.Struct({
  scope: ScopeId,
  source: SourceCredentialBindingSource,
  slotKey: Schema2.String
});
var ReplaceSourceCredentialBindingsInput = Schema2.Struct({
  scope: ScopeId,
  source: SourceCredentialBindingSource,
  slotPrefixes: Schema2.Array(Schema2.String),
  bindings: Schema2.Array(ReplaceCredentialBindingValue)
});
var CredentialBindingResolutionStatus = Schema2.Literals([
  "resolved",
  "missing",
  "blocked"
]);
var ResolvedCredentialSlot = Schema2.Struct({
  pluginId: Schema2.String,
  sourceId: Schema2.String,
  sourceScopeId: ScopeId,
  slotKey: Schema2.String,
  bindingScopeId: Schema2.NullOr(ScopeId),
  kind: Schema2.NullOr(CredentialBindingKind),
  status: CredentialBindingResolutionStatus
});
var credentialBindingId = (input) => CredentialBindingId.make(
  JSON.stringify([input.pluginId, input.sourceScope, input.sourceId, input.slotKey])
);
var credentialSlotPart = (value) => value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "default";
var credentialSlotKey = (prefix, name) => `${prefix}:${credentialSlotPart(name)}`;
var credentialBindingValueFromRow = (row) => Match.value(row).pipe(
  Match.when({ kind: "text" }, ({ text_value }) => ({
    kind: "text",
    text: text_value
  })),
  Match.when({ kind: "secret" }, ({ scope_id, secret_id, secret_scope_id }) => ({
    kind: "secret",
    secretId: SecretId.make(secret_id),
    secretScopeId: ScopeId.make(secret_scope_id ?? scope_id)
  })),
  Match.when({ kind: "connection" }, ({ connection_id }) => ({
    kind: "connection",
    connectionId: ConnectionId.make(connection_id)
  })),
  Match.exhaustive
);
var credentialBindingRowToRef = (row) => {
  const value = credentialBindingValueFromRow(row);
  return CredentialBindingRef.make({
    id: CredentialBindingId.make(row.id),
    scopeId: ScopeId.make(row.scope_id),
    pluginId: row.plugin_id,
    sourceId: row.source_id,
    sourceScopeId: ScopeId.make(row.source_scope_id),
    slotKey: row.slot_key,
    value,
    createdAt: row.created_at instanceof Date ? row.created_at : new Date(row.created_at),
    updatedAt: row.updated_at instanceof Date ? row.updated_at : new Date(row.updated_at)
  });
};

// src/oauth.ts
import { Effect as Effect3, Schema as Schema3 } from "effect";
var OAuthDynamicDcrStrategy = Schema3.Struct({
  kind: Schema3.Literal("dynamic-dcr"),
  /** Scopes to request. Defaults to whatever `scopes_supported`
   *  advertises; caller can narrow or extend. */
  scopes: Schema3.optional(Schema3.Array(Schema3.String))
});
var OAuthAuthorizationCodeStrategy = Schema3.Struct({
  kind: Schema3.Literal("authorization-code"),
  authorizationEndpoint: Schema3.String,
  tokenEndpoint: Schema3.String,
  /** Expected authorization-server issuer for ID token validation. Some
   *  providers use a token endpoint host that differs from issuer, or a
   *  path-scoped issuer such as Okta custom authorization servers. */
  issuerUrl: Schema3.optional(Schema3.NullOr(Schema3.String)),
  /** Secret id holding the `client_id`. Using a secret row rather than
   *  an inline string so the value lives at the scope where the caller
   *  configured it and shadowing behaves consistently. */
  clientIdSecretId: Schema3.String,
  clientIdSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
  /** Secret id for `client_secret`. Null for public clients using
   *  PKCE without a confidential secret. */
  clientSecretSecretId: Schema3.NullOr(Schema3.String),
  clientSecretSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
  scopes: Schema3.Array(Schema3.String),
  /** Separator between scopes. RFC 6749 says space; some providers
   *  (GitHub classic) use comma. */
  scopeSeparator: Schema3.optional(Schema3.String),
  /** Provider-specific params injected at authorization URL build time
   *  (Google's `access_type=offline`, `prompt=consent`, ...). */
  extraAuthorizationParams: Schema3.optional(Schema3.Record(Schema3.String, Schema3.String)),
  /** `"body"` (default) sends client creds in the form body; `"basic"`
   *  uses HTTP Basic auth. Stripe-style servers require basic. */
  clientAuth: Schema3.optional(Schema3.Literals(["body", "basic"]))
});
var OAuthClientCredentialsStrategy = Schema3.Struct({
  kind: Schema3.Literal("client-credentials"),
  tokenEndpoint: Schema3.String,
  clientIdSecretId: Schema3.String,
  clientIdSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
  clientSecretSecretId: Schema3.String,
  clientSecretSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
  scopes: Schema3.optional(Schema3.Array(Schema3.String)),
  scopeSeparator: Schema3.optional(Schema3.String),
  clientAuth: Schema3.optional(Schema3.Literals(["body", "basic"]))
});
var OAuthStrategy = Schema3.Union([
  OAuthDynamicDcrStrategy,
  OAuthAuthorizationCodeStrategy,
  OAuthClientCredentialsStrategy
]);
var OAuthProviderState = Schema3.Union([
  Schema3.Struct({
    kind: Schema3.Literal("dynamic-dcr"),
    tokenEndpoint: Schema3.String,
    issuerUrl: Schema3.optional(Schema3.NullOr(Schema3.String)),
    authorizationServerUrl: Schema3.optional(Schema3.NullOr(Schema3.String)),
    authorizationServerMetadataUrl: Schema3.NullOr(Schema3.String),
    idTokenSigningAlgValuesSupported: Schema3.optional(Schema3.Array(Schema3.String)),
    /** DCR-minted client_id. Embedded inline (not a secret) — DCR
     *  clients are public-ish by design; the secret part (if the AS
     *  issued one) is a separate secret row. */
    clientId: Schema3.String,
    clientSecretSecretId: Schema3.NullOr(Schema3.String),
    clientSecretSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
    clientAuth: Schema3.Literals(["body", "basic"]),
    scopes: Schema3.Array(Schema3.String).pipe(Schema3.withDecodingDefaultType(Effect3.succeed([]))),
    scopeSeparator: Schema3.optional(Schema3.String),
    scope: Schema3.NullOr(Schema3.String),
    /** RFC 8707 canonical resource URL. Replayed on refresh so the new
     *  access token's audience stays bound to the same resource. */
    resource: Schema3.optional(Schema3.NullOr(Schema3.String))
  }),
  Schema3.Struct({
    kind: Schema3.Literal("authorization-code"),
    tokenEndpoint: Schema3.String,
    issuerUrl: Schema3.optional(Schema3.NullOr(Schema3.String)),
    clientIdSecretId: Schema3.String,
    clientIdSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
    clientSecretSecretId: Schema3.NullOr(Schema3.String),
    clientSecretSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
    clientAuth: Schema3.Literals(["body", "basic"]),
    scopes: Schema3.Array(Schema3.String).pipe(Schema3.withDecodingDefaultType(Effect3.succeed([]))),
    scopeSeparator: Schema3.optional(Schema3.String),
    scope: Schema3.NullOr(Schema3.String),
    resource: Schema3.optional(Schema3.NullOr(Schema3.String))
  }),
  Schema3.Struct({
    kind: Schema3.Literal("client-credentials"),
    tokenEndpoint: Schema3.String,
    clientIdSecretId: Schema3.String,
    clientIdSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
    clientSecretSecretId: Schema3.String,
    clientSecretSecretScopeId: Schema3.optional(Schema3.NullOr(Schema3.String)),
    scopes: Schema3.Array(Schema3.String),
    scopeSeparator: Schema3.optional(Schema3.String),
    clientAuth: Schema3.Literals(["body", "basic"]),
    scope: Schema3.NullOr(Schema3.String)
  })
]);
var OAUTH2_PROVIDER_KEY = "oauth2";
var OAuthProbeError = class extends Schema3.TaggedErrorClass()(
  "OAuthProbeError",
  {
    message: Schema3.String
  },
  { httpApiStatus: 400 }
) {
};
var OAuthStartError = class extends Schema3.TaggedErrorClass()(
  "OAuthStartError",
  {
    message: Schema3.String,
    /** RFC 6749 §5.2 / RFC 7591 §3.2.2 error code propagated up from the
     *  authorization server (e.g. `invalid_client_metadata`). UI surfaces
     *  it as the structured "AS rejected the registration" reason. */
    error: Schema3.optional(Schema3.String),
    errorDescription: Schema3.optional(Schema3.String)
  },
  { httpApiStatus: 400 }
) {
};
var OAuthCompleteError = class extends Schema3.TaggedErrorClass()(
  "OAuthCompleteError",
  {
    message: Schema3.String,
    /** RFC 6749 §5.2 error code, when the token endpoint returned one.
     *  Callers distinguish terminal failures (`invalid_grant` ⇒
     *  re-auth required) from transient ones. */
    code: Schema3.optional(Schema3.String)
  },
  { httpApiStatus: 400 }
) {
};
var OAuthSessionNotFoundError = class extends Schema3.TaggedErrorClass()(
  "OAuthSessionNotFoundError",
  {
    sessionId: Schema3.String
  },
  { httpApiStatus: 404 }
) {
};
var OAUTH2_SESSION_TTL_MS = 15 * 60 * 1e3;

// src/policies.ts
import { Match as Match2, Schema as Schema4 } from "effect";
var matchPattern = (pattern, toolId) => {
  if (pattern === "*") return true;
  if (pattern === toolId) return true;
  if (pattern.endsWith(".*")) {
    const prefix = pattern.slice(0, -2);
    if (prefix.length === 0) return false;
    return toolId === prefix || toolId.startsWith(`${prefix}.`);
  }
  return false;
};
var isValidPattern = (pattern) => {
  if (pattern.length === 0) return false;
  if (pattern === "*") return true;
  if (pattern.startsWith(".") || pattern.endsWith(".")) return false;
  if (pattern.includes("..")) return false;
  if (pattern.startsWith("*")) return false;
  const segments = pattern.split(".");
  for (let i = 0; i < segments.length; i++) {
    const seg = segments[i];
    if (seg.length === 0) return false;
    if (seg.includes("*") && seg !== "*") return false;
    if (seg === "*" && i !== segments.length - 1) return false;
  }
  return true;
};
var comparePolicyRow = (a, b) => {
  const pa = a.position;
  const pb = b.position;
  if (pa < pb) return -1;
  if (pa > pb) return 1;
  const ia = a.id;
  const ib = b.id;
  return ia < ib ? -1 : ia > ib ? 1 : 0;
};
var actionRestrictionRank = (action) => Match2.value(action).pipe(
  Match2.when("block", () => 3),
  Match2.when("require_approval", () => 2),
  Match2.when("approve", () => 1),
  Match2.exhaustive
);
var moreRestrictive = (current, candidate) => {
  if (!current) return candidate;
  const currentRank = actionRestrictionRank(current.action);
  const candidateRank = actionRestrictionRank(candidate.action);
  return candidateRank > currentRank ? candidate : current;
};
var resolveToolPolicy = (toolId, policies, scopeRank) => {
  if (policies.length === 0) return void 0;
  const sorted = [...policies].sort((a, b) => {
    const sa = scopeRank(a);
    const sb = scopeRank(b);
    if (sa !== sb) return sa - sb;
    return comparePolicyRow(a, b);
  });
  const firstMatchByScope = /* @__PURE__ */ new Map();
  for (const row of sorted) {
    if (firstMatchByScope.has(row.scope_id)) continue;
    if (matchPattern(row.pattern, toolId)) {
      firstMatchByScope.set(row.scope_id, {
        action: row.action,
        pattern: row.pattern,
        policyId: row.id
      });
    }
  }
  let selected;
  for (const match of firstMatchByScope.values()) {
    selected = moreRestrictive(selected, match);
  }
  return selected;
};
var liftPlugin = (defaultRequiresApproval) => defaultRequiresApproval ? { action: "require_approval", source: "plugin-default" } : { action: "approve", source: "plugin-default" };
var liftUser = (match) => ({
  action: match.action,
  source: "user",
  pattern: match.pattern,
  policyId: match.policyId
});
var resolveEffectivePolicy = (toolId, policies, scopeRank, defaultRequiresApproval) => {
  const match = resolveToolPolicy(toolId, policies, scopeRank);
  return match ? liftUser(match) : liftPlugin(defaultRequiresApproval);
};
var effectivePolicyFromSorted = (toolId, sortedPolicies, defaultRequiresApproval) => {
  const firstMatchByScope = /* @__PURE__ */ new Map();
  for (const p of sortedPolicies) {
    const scopeKey = "scopeId" in p && p.scopeId ? String(p.scopeId) : "__flat__";
    if (firstMatchByScope.has(scopeKey)) continue;
    if (matchPattern(p.pattern, toolId)) {
      firstMatchByScope.set(scopeKey, {
        action: p.action,
        source: "user",
        pattern: p.pattern,
        policyId: p.id
      });
    }
  }
  let selected;
  for (const match of firstMatchByScope.values()) {
    selected = moreRestrictive(selected, match);
  }
  return selected ?? liftPlugin(defaultRequiresApproval);
};
var rowToToolPolicy = (row) => ({
  id: PolicyId.make(row.id),
  scopeId: ScopeId.make(row.scope_id),
  pattern: row.pattern,
  action: row.action,
  position: row.position,
  createdAt: row.created_at,
  updatedAt: row.updated_at
});
var ToolPolicyActionSchema = Schema4.Literals(["approve", "require_approval", "block"]);

// src/types.ts
import { Schema as Schema5 } from "effect";
var ToolSchema = Schema5.Struct({
  id: ToolId,
  name: Schema5.optional(Schema5.String),
  description: Schema5.optional(Schema5.String),
  inputSchema: Schema5.optional(Schema5.Unknown),
  outputSchema: Schema5.optional(Schema5.Unknown),
  schemaDefinitions: Schema5.optional(Schema5.Record(Schema5.String, Schema5.Unknown)),
  inputTypeScript: Schema5.optional(Schema5.String),
  outputTypeScript: Schema5.optional(Schema5.String),
  typeScriptDefinitions: Schema5.optional(Schema5.Record(Schema5.String, Schema5.String))
});
var SourceDetectionResult = Schema5.Struct({
  /** Plugin id that recognized the URL (e.g. "openapi", "graphql"). */
  kind: Schema5.String,
  /** Confidence tier — UI uses this to pick a winner when multiple
   *  plugins claim a URL. */
  confidence: Schema5.Literals(["high", "medium", "low"]),
  /** The (possibly normalized) endpoint the plugin will use. */
  endpoint: Schema5.String,
  /** Human-readable name suggestion, typically derived from spec title
   *  or URL hostname. */
  name: Schema5.String,
  /** Namespace suggestion — the plugin's recommendation for the source
   *  id. UI may override. */
  namespace: Schema5.String
});

// src/usages.ts
import { Schema as Schema6 } from "effect";
var Usage = Schema6.Struct({
  pluginId: Schema6.String,
  scopeId: ScopeId,
  ownerKind: Schema6.String,
  ownerId: Schema6.String,
  ownerName: Schema6.NullOr(Schema6.String),
  slot: Schema6.String
});

// src/errors.ts
import { Data as Data2, Schema as Schema7 } from "effect";
var ToolNotFoundError = class extends Schema7.TaggedErrorClass()(
  "ToolNotFoundError",
  {
    toolId: ToolId,
    suggestions: Schema7.optional(Schema7.Array(ToolId))
  }
) {
};
var ToolInvocationError = class extends Data2.TaggedError("ToolInvocationError") {
};
var PluginNotLoadedError = class extends Schema7.TaggedErrorClass()(
  "PluginNotLoadedError",
  {
    pluginId: Schema7.String,
    toolId: ToolId
  }
) {
};
var NoHandlerError = class extends Schema7.TaggedErrorClass()("NoHandlerError", {
  toolId: ToolId,
  pluginId: Schema7.String
}) {
};
var ToolBlockedError = class extends Schema7.TaggedErrorClass()(
  "ToolBlockedError",
  {
    toolId: ToolId,
    pattern: Schema7.String
  }
) {
};
var SourceNotFoundError = class extends Schema7.TaggedErrorClass()(
  "SourceNotFoundError",
  { sourceId: Schema7.String }
) {
};
var SourceRemovalNotAllowedError = class extends Schema7.TaggedErrorClass()(
  "SourceRemovalNotAllowedError",
  { sourceId: Schema7.String }
) {
};
var SecretNotFoundError = class extends Schema7.TaggedErrorClass()(
  "SecretNotFoundError",
  { secretId: SecretId }
) {
};
var SecretResolutionError = class extends Schema7.TaggedErrorClass()(
  "SecretResolutionError",
  {
    secretId: SecretId,
    message: Schema7.String
  }
) {
};
var SecretOwnedByConnectionError = class extends Schema7.TaggedErrorClass()(
  "SecretOwnedByConnectionError",
  {
    secretId: SecretId,
    connectionId: ConnectionId
  }
) {
};
var SecretInUseError = class extends Schema7.TaggedErrorClass()(
  "SecretInUseError",
  {
    secretId: SecretId,
    usageCount: Schema7.Number
  }
) {
};
var ConnectionNotFoundError = class extends Schema7.TaggedErrorClass()(
  "ConnectionNotFoundError",
  { connectionId: ConnectionId }
) {
};
var ConnectionProviderNotRegisteredError = class extends Schema7.TaggedErrorClass()(
  "ConnectionProviderNotRegisteredError",
  {
    provider: Schema7.String,
    connectionId: Schema7.optional(ConnectionId)
  }
) {
};
var ConnectionRefreshNotSupportedError = class extends Schema7.TaggedErrorClass()(
  "ConnectionRefreshNotSupportedError",
  {
    connectionId: ConnectionId,
    provider: Schema7.String
  }
) {
};
var ConnectionReauthRequiredError = class extends Schema7.TaggedErrorClass()(
  "ConnectionReauthRequiredError",
  {
    connectionId: ConnectionId,
    provider: Schema7.String,
    message: Schema7.String
  }
) {
};
var ConnectionInUseError = class extends Schema7.TaggedErrorClass()(
  "ConnectionInUseError",
  {
    connectionId: ConnectionId,
    usageCount: Schema7.Number
  }
) {
};

// src/plugin-storage.ts
var pluginStorageId = (input) => JSON.stringify([input.pluginId, input.collection, input.key]);

export {
  StorageError,
  UniqueViolationError,
  isStorageFailure,
  makeFumaClient,
  ScopeId,
  ToolId,
  SecretId,
  PolicyId,
  ConnectionId,
  CredentialBindingId,
  assertExecutorScopePolicyTable,
  textColumn,
  nullableTextColumn,
  boolColumn,
  bigintColumn,
  nullableBigintColumn,
  jsonColumn,
  nullableJsonColumn,
  dateColumn,
  scopedExecutorTable,
  coreSchema,
  TOOL_POLICY_ACTIONS,
  isToolPolicyAction,
  CredentialBindingKind,
  CredentialBindingValue,
  ConfiguredCredentialBinding,
  ConfiguredCredentialValue,
  ScopedSecretCredentialInput,
  CredentialBindingRef,
  CredentialBindingSlotInput,
  RemoveCredentialBindingInput,
  ReplaceCredentialBindingValue,
  ReplaceCredentialBindingsInput,
  SourceCredentialBindingSource,
  SourceCredentialBindingSourceInput,
  SourceCredentialBindingSlotInput,
  SetSourceCredentialBindingInput,
  RemoveSourceCredentialBindingInput,
  ReplaceSourceCredentialBindingsInput,
  CredentialBindingResolutionStatus,
  ResolvedCredentialSlot,
  credentialBindingId,
  credentialSlotPart,
  credentialSlotKey,
  credentialBindingValueFromRow,
  credentialBindingRowToRef,
  OAuthDynamicDcrStrategy,
  OAuthAuthorizationCodeStrategy,
  OAuthClientCredentialsStrategy,
  OAuthStrategy,
  OAuthProviderState,
  OAUTH2_PROVIDER_KEY,
  OAuthProbeError,
  OAuthStartError,
  OAuthCompleteError,
  OAuthSessionNotFoundError,
  OAUTH2_SESSION_TTL_MS,
  matchPattern,
  isValidPattern,
  comparePolicyRow,
  resolveToolPolicy,
  resolveEffectivePolicy,
  effectivePolicyFromSorted,
  rowToToolPolicy,
  ToolPolicyActionSchema,
  ToolSchema,
  SourceDetectionResult,
  Usage,
  ToolNotFoundError,
  ToolInvocationError,
  PluginNotLoadedError,
  NoHandlerError,
  ToolBlockedError,
  SourceNotFoundError,
  SourceRemovalNotAllowedError,
  SecretNotFoundError,
  SecretResolutionError,
  SecretOwnedByConnectionError,
  SecretInUseError,
  ConnectionNotFoundError,
  ConnectionProviderNotRegisteredError,
  ConnectionRefreshNotSupportedError,
  ConnectionReauthRequiredError,
  ConnectionInUseError,
  pluginStorageId
};
//# sourceMappingURL=chunk-ZANQD7E2.js.map