@protobase/server 0.33.3 → 0.34.0
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/assistant/query-tools.js +1 -1
- package/dist/auth/jwt.d.ts +15 -1
- package/dist/auth/jwt.js +41 -5
- package/dist/better-auth/authenticator.d.ts +16 -1
- package/dist/better-auth/authenticator.js +41 -24
- package/dist/better-auth/create-auth.d.ts +3063 -364
- package/dist/better-auth/create-auth.js +36 -19
- package/dist/better-auth/mcp/connected-apps.d.ts +13 -0
- package/dist/better-auth/mcp/connected-apps.js +86 -0
- package/dist/better-auth/mcp/consent-check.js +38 -0
- package/dist/better-auth/mcp/consent-reference.js +16 -0
- package/dist/better-auth/mcp/discovery-routes.js +19 -0
- package/dist/better-auth/mcp/grant-reference.js +25 -0
- package/dist/better-auth/mcp/mcp-plugins.d.ts +13 -0
- package/dist/better-auth/mcp/mcp-plugins.js +107 -0
- package/dist/better-auth/mcp/mcp-token-claims.js +39 -0
- package/dist/better-auth/mcp/request-defaults.js +57 -0
- package/dist/better-auth/mcp/revoke-grants.js +75 -0
- package/dist/better-auth/mcp/setup-gate.js +38 -0
- package/dist/better-auth/mcp/signed-query-guard.js +29 -0
- package/dist/better-auth/origins.d.ts +7 -0
- package/dist/better-auth/origins.js +8 -1
- package/dist/better-auth/password-reset.js +4 -3
- package/dist/better-auth/policy-plugin.js +1 -24
- package/dist/better-auth/session-token.js +26 -0
- package/dist/better-auth/sign-in-enforcement.js +6 -1
- package/dist/better-auth/sign-in-setup.js +38 -0
- package/dist/better-auth/snake-case-names.js +102 -1
- package/dist/better-auth/staff-checks.js +9 -2
- package/dist/better-auth/staff-plugin.js +9 -2
- package/dist/better-auth/status-route.js +2 -1
- package/dist/better-auth/token-claims.js +19 -0
- package/dist/better-auth/users.d.ts +4 -1
- package/dist/better-auth/users.js +6 -1
- package/dist/check-roles.js +1 -1
- package/dist/create-admin.js +22 -2
- package/dist/deps.d.ts +1 -0
- package/dist/encryption/apply.d.ts +40 -0
- package/dist/encryption/apply.js +99 -0
- package/dist/encryption/binding.d.ts +2 -0
- package/dist/encryption/binding.js +53 -0
- package/dist/encryption/capture-off.js +12 -0
- package/dist/encryption/cascading-keys.d.ts +9 -0
- package/dist/encryption/cascading-keys.js +21 -0
- package/dist/encryption/envelope-open.d.ts +5 -0
- package/dist/encryption/envelope-open.js +57 -0
- package/dist/encryption/envelope-seal.js +38 -0
- package/dist/encryption/keyring.js +60 -0
- package/dist/encryption/mask-stored.js +16 -0
- package/dist/encryption/rebind-check.js +28 -0
- package/dist/encryption/remnants.js +53 -0
- package/dist/encryption/runtime.d.ts +1 -0
- package/dist/encryption/runtime.js +18 -0
- package/dist/encryption/scan.d.ts +4 -0
- package/dist/encryption/scan.js +61 -0
- package/dist/encryption/seal-values.js +30 -0
- package/dist/encryption/shared-columns.js +19 -0
- package/dist/encryption/status.d.ts +39 -0
- package/dist/encryption/status.js +92 -0
- package/dist/encryption/stored-value.js +16 -0
- package/dist/encryption/tools.d.ts +26 -0
- package/dist/encryption/tools.js +34 -0
- package/dist/forms/check-forms.js +1 -1
- package/dist/functions/accept-socket.js +32 -0
- package/dist/functions/define-function.d.ts +7 -0
- package/dist/functions/function-socket.d.ts +18 -0
- package/dist/functions/function-socket.js +81 -0
- package/dist/functions/routes.js +33 -8
- package/dist/functions/same-caller.js +9 -0
- package/dist/functions/socket-recheck.js +33 -0
- package/dist/functions/upgrade-caller.js +25 -0
- package/dist/gotrue/user-routes.js +6 -0
- package/dist/index.d.ts +10 -5
- package/dist/index.js +3 -2
- package/dist/records.js +3 -3
- package/dist/request-access.js +9 -5
- package/dist/rest/encrypted-columns.js +37 -0
- package/dist/rest/table-routes.js +25 -13
- package/dist/reveal-service.js +17 -3
- package/dist/types.d.ts +5 -0
- package/dist/validate-body.js +4 -2
- package/dist/webhooks/attempt.js +5 -1
- package/dist/webhooks/subscriber-view.js +14 -1
- package/dist/write-pipeline.js +14 -2
- package/dist/write-shared.js +7 -3
- package/dist/write-update.js +12 -2
- package/package.json +11 -7
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { bindingOf } from "./binding.js";
|
|
2
|
+
import { envelopePrefix } from "./envelope-seal.js";
|
|
3
|
+
import { columnId, tableId } from "../sql-parts.js";
|
|
4
|
+
import { UnreadableValue, openText } from "./envelope-open.js";
|
|
5
|
+
import { cascadingKeys } from "./cascading-keys.js";
|
|
6
|
+
import { historyRemnants, outboxRemnants } from "./remnants.js";
|
|
7
|
+
import { scanColumn } from "./scan.js";
|
|
8
|
+
import { sql } from "kysely";
|
|
9
|
+
//#region src/encryption/status.ts
|
|
10
|
+
const encryptedFields = (entry) => Object.values(entry.model.fields).filter((field) => field.encrypted);
|
|
11
|
+
/** Opens one scanned value: its plaintext and key id, or why it does not open. A value that is no envelope is plaintext. */
|
|
12
|
+
const examine = (keyring, entry, field, row, binding = bindingOf(entry.model, field, row.record)) => {
|
|
13
|
+
if (!row.stored.startsWith("pbenc:")) return { kind: "plaintext" };
|
|
14
|
+
try {
|
|
15
|
+
return {
|
|
16
|
+
kind: "open",
|
|
17
|
+
plaintext: openText(keyring, binding, row.stored, {
|
|
18
|
+
resource: entry.name,
|
|
19
|
+
field: field.name
|
|
20
|
+
}),
|
|
21
|
+
kid: row.stored.split(":")[2]
|
|
22
|
+
};
|
|
23
|
+
} catch (error) {
|
|
24
|
+
if (!(error instanceof UnreadableValue)) throw error;
|
|
25
|
+
return {
|
|
26
|
+
kind: "unreadable",
|
|
27
|
+
entry: {
|
|
28
|
+
key: entry.model.primaryKey.map((name) => String(row.record[name])),
|
|
29
|
+
...error.kid && { kid: error.kid },
|
|
30
|
+
kind: error.kind
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const fieldStatus = async (db, entry, field, keyring, changesSchema) => {
|
|
36
|
+
const status = {
|
|
37
|
+
resource: entry.name,
|
|
38
|
+
field: field.name,
|
|
39
|
+
byKey: {},
|
|
40
|
+
plaintext: 0,
|
|
41
|
+
unreadable: [],
|
|
42
|
+
history: 0,
|
|
43
|
+
outbox: 0
|
|
44
|
+
};
|
|
45
|
+
await scanColumn(db, entry, field, async (rows) => {
|
|
46
|
+
for (const row of rows) {
|
|
47
|
+
const found = examine(keyring, entry, field, row);
|
|
48
|
+
if (found.kind === "plaintext") status.plaintext++;
|
|
49
|
+
else if (found.kind === "open") status.byKey[found.kid] = (status.byKey[found.kid] ?? 0) + 1;
|
|
50
|
+
else status.unreadable.push(found.entry);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
status.history = await historyRemnants(db, changesSchema, entry.model, field);
|
|
54
|
+
status.outbox = await outboxRemnants(db, changesSchema, entry.model, field);
|
|
55
|
+
return status;
|
|
56
|
+
};
|
|
57
|
+
const strayValues = async (db, entry) => {
|
|
58
|
+
const fields = Object.values(entry.model.fields).filter((field) => field.type === "text" && !field.encrypted);
|
|
59
|
+
const stray = [];
|
|
60
|
+
for (const field of fields) {
|
|
61
|
+
const { rows } = await sql`select count(*)::text as count from ${tableId(entry.model)} where ${columnId(field)} like ${`${envelopePrefix}%`}`.execute(db);
|
|
62
|
+
const count = Number(rows[0].count);
|
|
63
|
+
if (count > 0) stray.push({
|
|
64
|
+
resource: entry.name,
|
|
65
|
+
field: field.name,
|
|
66
|
+
count
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return stray;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Per encrypted field: the values by key, the plaintext ones, those that do not open, and the old plaintext left in the
|
|
73
|
+
* history and the outbox; envelopes in fields that are not encrypted; foreign keys that rewrite a key. It writes nothing.
|
|
74
|
+
*/
|
|
75
|
+
const encryptionStatus = async (db, entries, keyring, changesSchema) => {
|
|
76
|
+
const fields = [];
|
|
77
|
+
const stray = [];
|
|
78
|
+
const cascading = [];
|
|
79
|
+
for (const entry of entries) {
|
|
80
|
+
for (const field of encryptedFields(entry)) fields.push(await fieldStatus(db, entry, field, keyring, changesSchema));
|
|
81
|
+
stray.push(...await strayValues(db, entry));
|
|
82
|
+
if (encryptedFields(entry).length > 0) cascading.push(...await cascadingKeys(db, entry.model));
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
kid: keyring.current.id,
|
|
86
|
+
fields,
|
|
87
|
+
stray,
|
|
88
|
+
cascading
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
//#endregion
|
|
92
|
+
export { encryptedFields, encryptionStatus, examine };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Sealed } from "./envelope-seal.js";
|
|
2
|
+
//#region src/encryption/stored-value.ts
|
|
3
|
+
/**
|
|
4
|
+
* The value a record write sends for `field`: JSON as text, and for an encrypted field only `null` or a value `sealValues`
|
|
5
|
+
* sealed, so no write path stores plaintext in it.
|
|
6
|
+
*/
|
|
7
|
+
const storedValue = (field, value) => {
|
|
8
|
+
if (field.encrypted) {
|
|
9
|
+
if (value === null) return null;
|
|
10
|
+
if (value instanceof Sealed) return Sealed.textOf(value);
|
|
11
|
+
throw new Error(`"${field.name}" is encrypted, and its value was not sealed`);
|
|
12
|
+
}
|
|
13
|
+
return field.type === "json" && value !== null ? JSON.stringify(value) : value;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { storedValue };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { EventsOptions } from "../changes/events-options.js";
|
|
2
|
+
import { ResourceSource } from "../resource-source.js";
|
|
3
|
+
import { EncryptionStatus } from "./status.js";
|
|
4
|
+
import { ApplyOptions, ApplyResult } from "./apply.js";
|
|
5
|
+
import { Db } from "@protobase/query";
|
|
6
|
+
//#region src/encryption/tools.d.ts
|
|
7
|
+
export type EncryptionToolsInput = {
|
|
8
|
+
resources: ResourceSource[];
|
|
9
|
+
db: Db;
|
|
10
|
+
events?: EventsOptions;
|
|
11
|
+
env: Record<string, string | undefined>;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* What `protobase encryption status` and `apply` run on a project: `undefined` when it has no encrypted fields. It fails
|
|
15
|
+
* on the same config and key problems as the server's startup. `kid` is the id of the current key.
|
|
16
|
+
*/
|
|
17
|
+
export declare const createEncryptionTools: ({ resources, db, events, env }: EncryptionToolsInput) => {
|
|
18
|
+
kid: string;
|
|
19
|
+
/** What every encrypted field's column holds, and what remains of its plaintext; it writes nothing. */
|
|
20
|
+
status: () => Promise<EncryptionStatus>;
|
|
21
|
+
/** Encrypts the plaintext, moves previous keys' values to the current one, rebinds renamed ones, and scrubs remnants. */
|
|
22
|
+
apply: (options?: ApplyOptions) => Promise<ApplyResult>;
|
|
23
|
+
} | undefined;
|
|
24
|
+
/** The tools of a project with encrypted fields. */
|
|
25
|
+
export type EncryptionTools = NonNullable<ReturnType<typeof createEncryptionTools>>;
|
|
26
|
+
//#endregion
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { changesSchema } from "../changes/events-options.js";
|
|
2
|
+
import { createEncryptionRuntime } from "./runtime.js";
|
|
3
|
+
import { buildRegistry } from "../registry.js";
|
|
4
|
+
import { encryptionStatus } from "./status.js";
|
|
5
|
+
import { applyEncryption } from "./apply.js";
|
|
6
|
+
import { rebindProblem } from "./rebind-check.js";
|
|
7
|
+
//#region src/encryption/tools.ts
|
|
8
|
+
/**
|
|
9
|
+
* What `protobase encryption status` and `apply` run on a project: `undefined` when it has no encrypted fields. It fails
|
|
10
|
+
* on the same config and key problems as the server's startup. `kid` is the id of the current key.
|
|
11
|
+
*/
|
|
12
|
+
const createEncryptionTools = ({ resources, db, events, env }) => {
|
|
13
|
+
const { entries } = buildRegistry(resources);
|
|
14
|
+
const runtime = createEncryptionRuntime({
|
|
15
|
+
models: entries.map((entry) => entry.model),
|
|
16
|
+
env
|
|
17
|
+
});
|
|
18
|
+
if (!runtime) return void 0;
|
|
19
|
+
const { keyring } = runtime;
|
|
20
|
+
const schema = changesSchema(events);
|
|
21
|
+
return {
|
|
22
|
+
kid: keyring.current.id,
|
|
23
|
+
/** What every encrypted field's column holds, and what remains of its plaintext; it writes nothing. */
|
|
24
|
+
status: () => encryptionStatus(db, entries, keyring, schema),
|
|
25
|
+
/** Encrypts the plaintext, moves previous keys' values to the current one, rebinds renamed ones, and scrubs remnants. */
|
|
26
|
+
apply: async (options = {}) => {
|
|
27
|
+
const problem = options.rebind && rebindProblem(entries, options.rebind);
|
|
28
|
+
if (problem) throw new Error(problem);
|
|
29
|
+
return applyEncryption(db, entries, keyring, schema, options);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
//#endregion
|
|
34
|
+
export { createEncryptionTools };
|
|
@@ -20,7 +20,7 @@ const fieldErrors = (registry, { form, view }, granted) => {
|
|
|
20
20
|
const field = model.fields[name];
|
|
21
21
|
if (!field) return [`field "${name}" does not exist on ${view.resource}`];
|
|
22
22
|
if (field.readOnly) return [`field "${name}" is read-only, so nobody fills it in`];
|
|
23
|
-
if (field.sensitive) return [`field "${name}" is sensitive, and a public form
|
|
23
|
+
if (field.sensitive && !field.encrypted) return [`field "${name}" is sensitive, and a public form takes only encrypted ones of them`];
|
|
24
24
|
if (field.type === "relation") return [`field "${name}" is a relation, whose records a visitor cannot read to pick one`];
|
|
25
25
|
if (field.type === "file") return [`field "${name}" is a file field, and a visitor cannot upload`];
|
|
26
26
|
if (!plainTypes.includes(field.type)) return [`field "${name}" is ${field.type}, which a form has no input for`];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { HttpProblem } from "../problem.js";
|
|
2
|
+
import { socketEvents } from "./function-socket.js";
|
|
3
|
+
//#region src/functions/accept-socket.ts
|
|
4
|
+
const marker = "protobase-websocket";
|
|
5
|
+
/**
|
|
6
|
+
* One call's `acceptWebSocket` and what turns its answer into the upgrade. `accept` only records the events and returns
|
|
7
|
+
* a marker response; `answer` upgrades once the function has returned it, so a caller that is refused, or a function
|
|
8
|
+
* that throws, never gets a socket.
|
|
9
|
+
*/
|
|
10
|
+
const socketAcceptor = ({ c, upgradeWebSocket, report, recheck }) => {
|
|
11
|
+
let accepted;
|
|
12
|
+
const accept = (events) => {
|
|
13
|
+
if (c.req.header("upgrade")?.toLowerCase() !== "websocket") throw new HttpProblem(426, "upgrade-required", "Upgrade Required", "Open this function with a WebSocket", {}, { upgrade: "websocket" });
|
|
14
|
+
if (!upgradeWebSocket) throw new Error("This server does not accept WebSockets");
|
|
15
|
+
accepted = events;
|
|
16
|
+
return new Response(null, { headers: { [marker]: "accept" } });
|
|
17
|
+
};
|
|
18
|
+
const answer = (name, response) => {
|
|
19
|
+
if (!accepted) return response;
|
|
20
|
+
if (!response.headers.has(marker)) throw new Error(`The function "${name}" accepted a WebSocket but answered with another response`);
|
|
21
|
+
return upgradeWebSocket(c, socketEvents(accepted, {
|
|
22
|
+
report,
|
|
23
|
+
...recheck && { recheck }
|
|
24
|
+
}), { onError: report });
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
accept,
|
|
28
|
+
answer
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
export { socketAcceptor };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Session } from "../types.js";
|
|
2
2
|
import { Caller } from "../api-keys/resolve-caller.js";
|
|
3
|
+
import { SocketEvents } from "./function-socket.js";
|
|
3
4
|
import { FunctionRecords } from "./records.js";
|
|
4
5
|
import { Capability } from "@protobase/schema";
|
|
5
6
|
import { Db } from "@protobase/query";
|
|
@@ -12,6 +13,12 @@ export type PublicFunctionContext = {
|
|
|
12
13
|
db: Db;
|
|
13
14
|
/** The caller, through the app's own `authenticate`: rejects with a 401 problem when the request carries no valid token. */
|
|
14
15
|
caller: () => Promise<FunctionCaller>;
|
|
16
|
+
/**
|
|
17
|
+
* Answers a WebSocket upgrade with a socket: return its response. A request that is no upgrade is a 426 problem. A
|
|
18
|
+
* protected function's caller is checked again every minute while the socket is open, which closes with 1008 once
|
|
19
|
+
* they would be refused; a public function checks its own callers.
|
|
20
|
+
*/
|
|
21
|
+
acceptWebSocket: (events: SocketEvents) => Response;
|
|
15
22
|
};
|
|
16
23
|
/** Who called a function, and the app's resources as them. */
|
|
17
24
|
export type FunctionCaller = {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import "hono/ws";
|
|
2
|
+
//#region src/functions/function-socket.d.ts
|
|
3
|
+
/** An open WebSocket as a function sees it. */
|
|
4
|
+
export type FunctionSocket = {
|
|
5
|
+
/** Resolves once the data is written to the connection, or at once when the socket is closed; it never rejects. */
|
|
6
|
+
send(data: string | ArrayBuffer | Uint8Array): Promise<void>;
|
|
7
|
+
close(code?: number, reason?: string): void;
|
|
8
|
+
/** The bytes queued to send but not yet written. */
|
|
9
|
+
readonly bufferedAmount: number;
|
|
10
|
+
};
|
|
11
|
+
/** What a function's socket does: see `acceptWebSocket`. */
|
|
12
|
+
export type SocketEvents = {
|
|
13
|
+
onOpen?: (socket: FunctionSocket) => void | Promise<void>;
|
|
14
|
+
/** Text arrives as a string, binary as an ArrayBuffer. The next message waits until a returned promise settles. */
|
|
15
|
+
onMessage?: (data: string | ArrayBuffer, socket: FunctionSocket) => void | Promise<void>;
|
|
16
|
+
onClose?: (code: number, reason: string) => void | Promise<void>;
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { recheckWhileOpen } from "./socket-recheck.js";
|
|
2
|
+
//#region src/functions/function-socket.ts
|
|
3
|
+
const openState = 1;
|
|
4
|
+
/** Received bytes waiting for `onMessage` above which reading pauses. */
|
|
5
|
+
const pauseAboveBytes = 1 << 20;
|
|
6
|
+
/** Where reading cannot pause, the waiting bytes above which the socket closes with 1013 (Try Again Later). */
|
|
7
|
+
const closeAboveBytes = 16 << 20;
|
|
8
|
+
const sizeOf = (data) => typeof data === "string" ? data.length : data.byteLength;
|
|
9
|
+
/**
|
|
10
|
+
* A function's socket events as Hono's, over the host's raw socket. Messages reach `onMessage` one at a time, in order,
|
|
11
|
+
* after `onOpen`, and `onClose` comes after the last of them. A handler that throws or rejects is reported and closes
|
|
12
|
+
* the socket with 1011.
|
|
13
|
+
*/
|
|
14
|
+
const socketEvents = (events, { report, recheck }) => {
|
|
15
|
+
let raw;
|
|
16
|
+
let socket;
|
|
17
|
+
let chain = Promise.resolve();
|
|
18
|
+
let waiting = 0;
|
|
19
|
+
let paused = false;
|
|
20
|
+
let ended = false;
|
|
21
|
+
let stopRecheck = () => {};
|
|
22
|
+
const end = (code, reason) => {
|
|
23
|
+
ended = true;
|
|
24
|
+
stopRecheck();
|
|
25
|
+
raw.close(code, reason);
|
|
26
|
+
};
|
|
27
|
+
const fail = (error) => {
|
|
28
|
+
report(error);
|
|
29
|
+
if (!ended) end(1011, "Internal Error");
|
|
30
|
+
};
|
|
31
|
+
const enqueue = (step, always = false) => {
|
|
32
|
+
chain = chain.then(() => ended && !always ? void 0 : step()).catch(fail);
|
|
33
|
+
};
|
|
34
|
+
const received = (data) => {
|
|
35
|
+
const size = sizeOf(data);
|
|
36
|
+
waiting += size;
|
|
37
|
+
if (waiting > 1048576 && raw.pause && !paused) {
|
|
38
|
+
paused = true;
|
|
39
|
+
raw.pause();
|
|
40
|
+
}
|
|
41
|
+
if (waiting > 16777216 && !raw.pause && !ended) end(1013, "Try Again Later");
|
|
42
|
+
enqueue(async () => {
|
|
43
|
+
await events.onMessage?.(data, socket);
|
|
44
|
+
waiting -= size;
|
|
45
|
+
if (paused && waiting === 0) {
|
|
46
|
+
paused = false;
|
|
47
|
+
raw.resume?.();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
onOpen: (_event, ws) => {
|
|
53
|
+
raw = ws.raw;
|
|
54
|
+
socket = {
|
|
55
|
+
send: (data) => new Promise((resolve) => {
|
|
56
|
+
if (raw.readyState !== openState) return resolve();
|
|
57
|
+
raw.send(data, () => resolve());
|
|
58
|
+
}),
|
|
59
|
+
close: (code, reason) => raw.close(code, reason),
|
|
60
|
+
get bufferedAmount() {
|
|
61
|
+
return raw.bufferedAmount;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
if (recheck) stopRecheck = recheckWhileOpen({
|
|
65
|
+
check: recheck,
|
|
66
|
+
close: end,
|
|
67
|
+
report
|
|
68
|
+
});
|
|
69
|
+
enqueue(() => events.onOpen?.(socket));
|
|
70
|
+
},
|
|
71
|
+
onMessage: (event) => {
|
|
72
|
+
if (typeof event.data === "string" || event.data instanceof ArrayBuffer) received(event.data);
|
|
73
|
+
},
|
|
74
|
+
onClose: (event) => {
|
|
75
|
+
stopRecheck();
|
|
76
|
+
enqueue(() => events.onClose?.(event.code, event.reason), true);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
//#endregion
|
|
81
|
+
export { closeAboveBytes, pauseAboveBytes, socketEvents };
|
package/dist/functions/routes.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { notFound } from "../problem.js";
|
|
1
|
+
import { forbidden, notFound } from "../problem.js";
|
|
2
2
|
import { invokeFunction } from "./define-function.js";
|
|
3
3
|
import { runInBackground } from "../background-work.js";
|
|
4
|
+
import { socketAcceptor } from "./accept-socket.js";
|
|
4
5
|
import { functionGate, requireGate } from "./function-gate.js";
|
|
6
|
+
import { sameCaller } from "./same-caller.js";
|
|
5
7
|
import { Hono } from "hono";
|
|
6
8
|
import { cors } from "hono/cors";
|
|
7
9
|
//#region src/functions/routes.ts
|
|
@@ -10,17 +12,21 @@ const relativeRequest = (request, prefix) => {
|
|
|
10
12
|
url.pathname = url.pathname.slice(prefix.length) || "/";
|
|
11
13
|
return new Request(url, request);
|
|
12
14
|
};
|
|
15
|
+
const isUpgrade = (request) => request.headers.get("upgrade")?.toLowerCase() === "websocket";
|
|
13
16
|
/**
|
|
14
17
|
* Every function at `<basePath>/<name>` and below, any method. A protected function authenticates the request first, so
|
|
15
18
|
* a call without a valid token is the authenticator's 401 problem, and one its gate refuses a 403; a public one gets the caller only when it asks. Each
|
|
16
19
|
* call runs as background work, so calls that hold the database for long leave a connection to page requests. Once a
|
|
17
20
|
* call ends, failed or not, `wake` runs, so what it wrote reaches open pages without waiting for the dispatcher's poll.
|
|
21
|
+
* A function may answer an upgrade with a socket, only once it returned; a protected one's caller is checked again
|
|
22
|
+
* every minute while it is open.
|
|
18
23
|
*/
|
|
19
|
-
const functionRoutes = ({ basePath, functions, authenticate, access, db, records, onError, wake }) => {
|
|
24
|
+
const functionRoutes = ({ basePath, functions, authenticate, access, db, records, onError, wake, upgradeWebSocket, upgradeAuthenticate = authenticate, report }) => {
|
|
20
25
|
const app = new Hono().basePath(basePath);
|
|
21
26
|
app.onError(onError);
|
|
27
|
+
const sessionOf = (request) => isUpgrade(request) ? upgradeAuthenticate(request) : authenticate(request);
|
|
22
28
|
const callerOf = async (request) => {
|
|
23
|
-
const session = await
|
|
29
|
+
const session = await sessionOf(request);
|
|
24
30
|
return {
|
|
25
31
|
session,
|
|
26
32
|
records: records(session)
|
|
@@ -36,21 +42,40 @@ const functionRoutes = ({ basePath, functions, authenticate, access, db, records
|
|
|
36
42
|
const request = relativeRequest(c.req.raw, prefix);
|
|
37
43
|
if (options.public) {
|
|
38
44
|
let caller;
|
|
39
|
-
|
|
45
|
+
const acceptor = socketAcceptor({
|
|
46
|
+
c,
|
|
47
|
+
upgradeWebSocket,
|
|
48
|
+
report
|
|
49
|
+
});
|
|
50
|
+
const context = {
|
|
40
51
|
name,
|
|
41
52
|
db,
|
|
42
|
-
caller: () => caller ??= callerOf(c.req.raw)
|
|
43
|
-
|
|
53
|
+
caller: () => caller ??= callerOf(c.req.raw),
|
|
54
|
+
acceptWebSocket: acceptor.accept
|
|
55
|
+
};
|
|
56
|
+
return acceptor.answer(name, await invokeFunction(name, fn, request, context));
|
|
44
57
|
}
|
|
45
58
|
const caller = await callerOf(c.req.raw);
|
|
46
59
|
requireGate(name, gate, caller.session);
|
|
60
|
+
const recheck = async () => {
|
|
61
|
+
const again = await upgradeAuthenticate(c.req.raw);
|
|
62
|
+
requireGate(name, gate, again);
|
|
63
|
+
if (!sameCaller(caller.session, again)) throw forbidden("caller-changed", "Your access changed: open the socket again");
|
|
64
|
+
};
|
|
65
|
+
const acceptor = socketAcceptor({
|
|
66
|
+
c,
|
|
67
|
+
upgradeWebSocket,
|
|
68
|
+
report,
|
|
69
|
+
recheck
|
|
70
|
+
});
|
|
47
71
|
const context = {
|
|
48
72
|
name,
|
|
49
73
|
db,
|
|
50
74
|
...caller,
|
|
51
|
-
caller: async () => caller
|
|
75
|
+
caller: async () => caller,
|
|
76
|
+
acceptWebSocket: acceptor.accept
|
|
52
77
|
};
|
|
53
|
-
return invokeFunction(name, fn, request, context);
|
|
78
|
+
return acceptor.answer(name, await invokeFunction(name, fn, request, context));
|
|
54
79
|
})));
|
|
55
80
|
}
|
|
56
81
|
app.all("/*", (c) => {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/functions/same-caller.ts
|
|
2
|
+
const sameRoles = (a, b) => {
|
|
3
|
+
const roles = new Set(a);
|
|
4
|
+
return roles.size === new Set(b).size && b.every((role) => roles.has(role));
|
|
5
|
+
};
|
|
6
|
+
/** Whether two resolutions of a caller give the same user, tenant, organization and roles, in any order. */
|
|
7
|
+
const sameCaller = (a, b) => a.user.id === b.user.id && a.tenant === b.tenant && a.organization?.id === b.organization?.id && sameRoles(a.user.roles, b.user.roles);
|
|
8
|
+
//#endregion
|
|
9
|
+
export { sameCaller };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { HttpProblem } from "../problem.js";
|
|
2
|
+
//#region src/functions/socket-recheck.ts
|
|
3
|
+
const isRefusal = (error) => error instanceof HttpProblem && (error.status === 401 || error.status === 403);
|
|
4
|
+
/**
|
|
5
|
+
* Runs `check` every `everyMs` while a socket is open, one check after the other. A refusal closes the socket with 1008
|
|
6
|
+
* (Policy Violation) and the problem's title; any other error is reported and closes it with 1011, so an outage that
|
|
7
|
+
* stops the check ends the access too. Returns the function that stops it.
|
|
8
|
+
*/
|
|
9
|
+
const recheckWhileOpen = ({ check, close, report, everyMs = 6e4 }) => {
|
|
10
|
+
let stopped = false;
|
|
11
|
+
let timer;
|
|
12
|
+
const end = (error) => {
|
|
13
|
+
if (stopped) return;
|
|
14
|
+
stopped = true;
|
|
15
|
+
if (isRefusal(error)) return close(1008, error.title);
|
|
16
|
+
report(error);
|
|
17
|
+
close(1011, "Internal Error");
|
|
18
|
+
};
|
|
19
|
+
const run = () => check().then(() => {
|
|
20
|
+
if (!stopped) schedule();
|
|
21
|
+
}, end);
|
|
22
|
+
const schedule = () => {
|
|
23
|
+
timer = setTimeout(run, everyMs);
|
|
24
|
+
timer.unref?.();
|
|
25
|
+
};
|
|
26
|
+
schedule();
|
|
27
|
+
return () => {
|
|
28
|
+
stopped = true;
|
|
29
|
+
clearTimeout(timer);
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { recheckWhileOpen };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { forbidden } from "../problem.js";
|
|
2
|
+
//#region src/functions/upgrade-caller.ts
|
|
3
|
+
const hostOf = (url) => URL.canParse(url) ? new URL(url).host : void 0;
|
|
4
|
+
const allowedOrigin = (request, origins) => {
|
|
5
|
+
const origin = request.headers.get("origin");
|
|
6
|
+
if (origin === null) return true;
|
|
7
|
+
if (origins) return origins.includes(origin);
|
|
8
|
+
const host = hostOf(origin);
|
|
9
|
+
return host !== void 0 && host === new URL(request.url).host;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* The caller of a WebSocket upgrade, which a browser opens with its session cookie and no headers of its own: refused
|
|
13
|
+
* with 403 from a foreign origin (cross-site WebSocket hijacking), then by its bearer token when it has one, otherwise
|
|
14
|
+
* by the bearer token its cookie's session mints, which goes through `authenticate` with all the request's other
|
|
15
|
+
* headers, as a plain call would.
|
|
16
|
+
*/
|
|
17
|
+
const upgradeAuthenticator = ({ authenticate, origins, sessionToken }) => async (request) => {
|
|
18
|
+
if (!allowedOrigin(request, origins)) throw forbidden("foreign-origin", "This page’s origin may not open a socket to this app");
|
|
19
|
+
if (request.headers.has("authorization") || !request.headers.has("cookie") || !sessionToken) return authenticate(request);
|
|
20
|
+
const headers = new Headers(request.headers);
|
|
21
|
+
headers.set("authorization", `Bearer ${await sessionToken(request)}`);
|
|
22
|
+
return authenticate(new Request(request, { headers }));
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { upgradeAuthenticator };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { effectiveSignInPolicy } from "../better-auth/sign-in-policy.js";
|
|
2
2
|
import { readSignInPolicy } from "../better-auth/policy-store.js";
|
|
3
3
|
import { goTrueUser, userMetadata } from "./user-json.js";
|
|
4
|
+
import { revokeMcpGrants } from "../better-auth/mcp/revoke-grants.js";
|
|
4
5
|
import { checkNewAccountPassword } from "../better-auth/new-account-password.js";
|
|
5
6
|
import { goTrueTokens } from "./access-tokens.js";
|
|
6
7
|
import { GoTrueError } from "./errors.js";
|
|
@@ -22,6 +23,9 @@ const logoutScopes = [
|
|
|
22
23
|
/**
|
|
23
24
|
* The signed-in user's own endpoints, with their access token: `GET /user`, `PUT /user` for a new password or metadata,
|
|
24
25
|
* and `POST /logout`. A token whose session has ended, by signing out or a ban, is GoTrue's `session_not_found`.
|
|
26
|
+
* With MCP on, signing out everywhere or the other sessions, and setting a password, disconnect the user's MCP clients,
|
|
27
|
+
* as the same steps do through Better Auth: GoTrue has no way to tell a password reset from a change, so every new
|
|
28
|
+
* password does.
|
|
25
29
|
*/
|
|
26
30
|
const userRoutes = ({ auth, context }) => {
|
|
27
31
|
const claimsOf = accessClaimsOf(goTrueTokens({ auth }));
|
|
@@ -61,6 +65,7 @@ const userRoutes = ({ auth, context }) => {
|
|
|
61
65
|
model: "session",
|
|
62
66
|
where
|
|
63
67
|
});
|
|
68
|
+
if (scope !== "local" && auth.mcp) await revokeMcpGrants(adapter, claims.sub);
|
|
64
69
|
};
|
|
65
70
|
return new Hono().get("/user", async (c) => c.json(await userJson(await signedIn(c.req.raw)))).put("/user", async (c) => {
|
|
66
71
|
const { email, password, data } = await readBody(c.req.raw, updateBody);
|
|
@@ -78,6 +83,7 @@ const userRoutes = ({ auth, context }) => {
|
|
|
78
83
|
accountId: user.id,
|
|
79
84
|
password: hash
|
|
80
85
|
});
|
|
86
|
+
if (auth.mcp) await revokeMcpGrants(ctx.adapter, user.id);
|
|
81
87
|
}
|
|
82
88
|
const merged = data && Object.fromEntries(Object.entries({
|
|
83
89
|
...userMetadata(user.metadata),
|
package/dist/index.d.ts
CHANGED
|
@@ -2,13 +2,13 @@ import { MobileConfig } from "./mobile-config.js";
|
|
|
2
2
|
import { AppIdentity } from "./app-identity.js";
|
|
3
3
|
import { AppIcons, PngIcon, pngIcons } from "./web-app/app-icons.js";
|
|
4
4
|
import { StaffSignIn } from "./better-auth/staff-log.js";
|
|
5
|
+
import { RoleDefinition, RolesInput } from "./better-auth/organizations/role-definitions.js";
|
|
5
6
|
import { MailMessage, Mailer } from "./mail/smtp-mailer.js";
|
|
6
7
|
import { OperatorProvider, readOperatorSettings } from "./better-auth/operator-provider.js";
|
|
7
|
-
import { RoleDefinition, RolesInput } from "./better-auth/organizations/role-definitions.js";
|
|
8
8
|
import { OrganizationRole, StoredMember, StoredOrganization } from "./better-auth/organizations/store.js";
|
|
9
|
+
import { SignInPolicy, SignInRule, StaffAccessRule, defaultSignInPolicy, signInPolicyMethods } from "./better-auth/sign-in-policy.js";
|
|
9
10
|
import { OrganizationsOptions } from "./better-auth/organizations/options.js";
|
|
10
11
|
import { PlatformSignIn, readPlatformSignIn } from "./better-auth/platform-sign-in.js";
|
|
11
|
-
import { SignInPolicy, SignInRule, StaffAccessRule, defaultSignInPolicy, signInPolicyMethods } from "./better-auth/sign-in-policy.js";
|
|
12
12
|
import { EmailComponent, EmailOptions, EmailTemplate, RenderedEmail, defineEmail } from "./mail/define-email.js";
|
|
13
13
|
import { AdminAuth, CreateAuthOptions, UserCreatedHook, createAuth, normalizeRoles } from "./better-auth/create-auth.js";
|
|
14
14
|
import { EventsOptions } from "./changes/events-options.js";
|
|
@@ -24,6 +24,7 @@ import { FileProvider, FileStore, StoredObject } from "./files/store.js";
|
|
|
24
24
|
import { FilesOptions } from "./files/options.js";
|
|
25
25
|
import { ApiKeys, ApiKeysOptions, apiKeySettings, apiKeyVariables } from "./api-keys/api-key-settings.js";
|
|
26
26
|
import { Caller, CallerOptions, apiKeyCaller } from "./api-keys/resolve-caller.js";
|
|
27
|
+
import { FunctionSocket, SocketEvents } from "./functions/function-socket.js";
|
|
27
28
|
import { ErrorReportingOptions, ErrorReportingSettings, errorReportingSettings, errorReportingVariable } from "./error-reporting/error-reporting-settings.js";
|
|
28
29
|
import { ChatMessage, ChatTextPart, Completion, CompletionOptions, ModelError, ModelSettings, ReasoningDetail, ReasoningEffort, ToolCall, ToolSpec, streamChatCompletion } from "./assistant/chat-completions.js";
|
|
29
30
|
import { CleanupEntry, CleanupSchedule, ScheduledDelete, storageCleanupSchedule } from "./files/cleanup-schedule.js";
|
|
@@ -53,11 +54,11 @@ import { consoleAuditQueue } from "./audit/console-queue.js";
|
|
|
53
54
|
import { JwtOptions, JwtVerifyOptions, jwtAuthenticator, jwtVerifier } from "./auth/jwt.js";
|
|
54
55
|
import { HttpProblem, MissingCredentials, badRequest, forbidden, notFound, unauthorized } from "./problem.js";
|
|
55
56
|
import { TrustedApp, withTrustedApps } from "./better-auth/app-tokens.js";
|
|
56
|
-
import { BetterAuthAuthenticatorOptions, betterAuthAuthenticator, betterAuthTokens } from "./better-auth/authenticator.js";
|
|
57
|
+
import { BetterAuthAuthenticator, BetterAuthAuthenticatorOptions, betterAuthAuthenticator, betterAuthTokens } from "./better-auth/authenticator.js";
|
|
57
58
|
import { parseRoles } from "./better-auth/parse-roles.js";
|
|
58
59
|
import { LinkedAccount, NewUser, StoredUser, createUser, deleteUser, hasUsers, listUsers, roleChoices, setUserBanned, setUserRole } from "./better-auth/users.js";
|
|
59
60
|
import { IssueTokenOptions, issueToken, maxTokenTtlSeconds } from "./better-auth/tokens.js";
|
|
60
|
-
import { webauthnPath } from "./better-auth/origins.js";
|
|
61
|
+
import { isOAuthWellKnownPath, oauthWellKnownPaths, webauthnPath } from "./better-auth/origins.js";
|
|
61
62
|
import { goTruePath } from "./gotrue/keys.js";
|
|
62
63
|
import { supabasePath } from "./supabase-paths.js";
|
|
63
64
|
import { defaultAppName } from "./app-name.js";
|
|
@@ -96,6 +97,10 @@ import { S3Bucket, S3FilesOptions, S3ListPage, S3Object, s3FileStore, s3Files }
|
|
|
96
97
|
import { storageProvider } from "./files/storage-provider.js";
|
|
97
98
|
import { objectKey } from "./storage/object-key.js";
|
|
98
99
|
import { FileCleanupInput, createFileCleanup } from "./files/file-cleanup.js";
|
|
100
|
+
import { CascadingKey } from "./encryption/cascading-keys.js";
|
|
101
|
+
import { EncryptionStatus, FieldStatus, StrayValues, UnreadableEntry } from "./encryption/status.js";
|
|
102
|
+
import { ApplyOptions, ApplyResult, FieldApplied, RebindOption } from "./encryption/apply.js";
|
|
103
|
+
import { EncryptionTools, EncryptionToolsInput, createEncryptionTools } from "./encryption/tools.js";
|
|
99
104
|
import { FileObject, FileVariantObject } from "./files/present.js";
|
|
100
105
|
import { FileRef, formatUri, variantPath } from "./files/uri.js";
|
|
101
106
|
import { aspectRatio, fileSize, fileType, imageSize, processor } from "./files/processors.js";
|
|
@@ -105,4 +110,4 @@ import { isSchedule } from "./jobs/schedule.js";
|
|
|
105
110
|
import { DrainResult, JobsRuntime, StartJobsOptions, startJobs } from "./jobs/runtime.js";
|
|
106
111
|
import { jobsDrainApp } from "./jobs/drain-route.js";
|
|
107
112
|
import { checkJobsSchema, jobsSchema, jobsSchemaMigration } from "./jobs/schema.js";
|
|
108
|
-
export { type Admin, type AdminAuth, type AdminOptions, type ApiFunction, type ApiKeys, type ApiKeysOptions, type AppIcons, type AppIdentity, type ApprovalAnswer, type ApprovalRequest, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type Authenticator, type BetterAuthAuthenticatorOptions, type Caller, type CallerOptions, type CapturedRow, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentUsers, type Completion, type CompletionOptions, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FileCleanupInput, type FileLimits, type FileObject, type FileProvider, type FileRef, type FileStore, type FileVariantObject, type FilesOptions, type FunctionApp, type FunctionCaller, type FunctionContext, type FunctionEnv, type FunctionHandler, type FunctionOptions, type FunctionRecords, type FunctionSource, type HistoryOptions, HttpProblem, type IssueTokenOptions, type JobContext, type JobDefinition, type JobOptions, type JobsRuntime, type JwtOptions, type JwtVerifyOptions, type KeyFunctionContext, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type MemberInput, MissingCredentials, type MobileConfig, ModelError, type ModelSettings, type NewOrganization, type NewUser, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type PngIcon, type ProjectConfig, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type QueryOptions, type QueryResult, type ReasoningDetail, type ReasoningEffort, type RecordKeyInput, type RecordPage, type RenderedEmail, type ResourceChange, type ResourceSource, type RoleDefinition, type RolesInput, type RunContext, type RuntimeOptions, type S3Bucket, type S3FilesOptions, type S3ListPage, type S3Object, type ScanGuardMode, type ScheduledDelete, type Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredObject, type StoredOrganization, type StoredUser, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolCall, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type User, type UserCreatedHook, type ViewSource, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, addAppRoleToOwners, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, backgroundSettled, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, betterAuthTokens, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultAppName, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, goTruePath, handleDroppedConnections, hasUsers, imageSize, isBackgroundWork, isCaptured, isJobDefinition, isSchedule, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, objectKey, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, waitUntil, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
|
|
113
|
+
export { type Admin, type AdminAuth, type AdminOptions, type ApiFunction, type ApiKeys, type ApiKeysOptions, type AppIcons, type AppIdentity, type ApplyOptions, type ApplyResult, type ApprovalAnswer, type ApprovalRequest, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type Authenticator, type BetterAuthAuthenticator, type BetterAuthAuthenticatorOptions, type Caller, type CallerOptions, type CapturedRow, type CascadingKey, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentUsers, type Completion, type CompletionOptions, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EncryptionStatus, type EncryptionTools, type EncryptionToolsInput, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FieldApplied, type FieldStatus, type FileCleanupInput, type FileLimits, type FileObject, type FileProvider, type FileRef, type FileStore, type FileVariantObject, type FilesOptions, type FunctionApp, type FunctionCaller, type FunctionContext, type FunctionEnv, type FunctionHandler, type FunctionOptions, type FunctionRecords, type FunctionSocket, type FunctionSource, type HistoryOptions, HttpProblem, type IssueTokenOptions, type JobContext, type JobDefinition, type JobOptions, type JobsRuntime, type JwtOptions, type JwtVerifyOptions, type KeyFunctionContext, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type MemberInput, MissingCredentials, type MobileConfig, ModelError, type ModelSettings, type NewOrganization, type NewUser, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type PngIcon, type ProjectConfig, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type QueryOptions, type QueryResult, type ReasoningDetail, type ReasoningEffort, type RebindOption, type RecordKeyInput, type RecordPage, type RenderedEmail, type ResourceChange, type ResourceSource, type RoleDefinition, type RolesInput, type RunContext, type RuntimeOptions, type S3Bucket, type S3FilesOptions, type S3ListPage, type S3Object, type ScanGuardMode, type ScheduledDelete, type Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SocketEvents, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredObject, type StoredOrganization, type StoredUser, type StrayValues, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolCall, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type UnreadableEntry, type User, type UserCreatedHook, type ViewSource, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, addAppRoleToOwners, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, backgroundSettled, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, betterAuthTokens, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createUser, defaultAppName, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, goTruePath, handleDroppedConnections, hasUsers, imageSize, isBackgroundWork, isCaptured, isJobDefinition, isOAuthWellKnownPath, isSchedule, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, oauthWellKnownPaths, objectKey, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, waitUntil, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import { requestApproval } from "./assistant/approval.js";
|
|
|
17
17
|
import { withCacheBreakpoints } from "./assistant/cache-breakpoints.js";
|
|
18
18
|
import { runTurn } from "./assistant/turn.js";
|
|
19
19
|
import { consoleAuditQueue } from "./audit/console-queue.js";
|
|
20
|
-
import { webauthnPath } from "./better-auth/origins.js";
|
|
20
|
+
import { isOAuthWellKnownPath, oauthWellKnownPaths, webauthnPath } from "./better-auth/origins.js";
|
|
21
21
|
import { apiKeySettings, apiKeyVariables } from "./api-keys/api-key-settings.js";
|
|
22
22
|
import { apiKeyCaller } from "./api-keys/resolve-caller.js";
|
|
23
23
|
import { jwtAuthenticator, jwtVerifier } from "./auth/jwt.js";
|
|
@@ -76,8 +76,9 @@ import { requireEnv } from "./functions/require-env.js";
|
|
|
76
76
|
import { backgroundSettled, waitUntil } from "./functions/wait-until.js";
|
|
77
77
|
import { storeFile } from "./files/store-file.js";
|
|
78
78
|
import { createFileCleanup } from "./files/file-cleanup.js";
|
|
79
|
+
import { createEncryptionTools } from "./encryption/tools.js";
|
|
79
80
|
import { aspectRatio, fileSize, fileType, imageSize, processor } from "./files/processors.js";
|
|
80
81
|
import { defineEmail } from "./mail/define-email.js";
|
|
81
82
|
import { startJobs } from "./jobs/runtime.js";
|
|
82
83
|
import { jobsDrainApp } from "./jobs/drain-route.js";
|
|
83
|
-
export { FatalJobError, HttpProblem, MissingCredentials, ModelError, addAppRoleToOwners, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, backgroundSettled, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, betterAuthTokens, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultAppName, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, goTruePath, handleDroppedConnections, hasUsers, imageSize, isBackgroundWork, isCaptured, isJobDefinition, isSchedule, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, objectKey, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, waitUntil, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
|
|
84
|
+
export { FatalJobError, HttpProblem, MissingCredentials, ModelError, addAppRoleToOwners, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, backgroundSettled, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, betterAuthTokens, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createUser, defaultAppName, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, goTruePath, handleDroppedConnections, hasUsers, imageSize, isBackgroundWork, isCaptured, isJobDefinition, isOAuthWellKnownPath, isSchedule, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, oauthWellKnownPaths, objectKey, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, waitUntil, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
|