@constructive-io/express-context 0.9.0 → 0.10.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/esm/index.js +1 -1
- package/esm/loaders/compute.js +57 -0
- package/esm/loaders/create-loader.js +10 -1
- package/esm/loaders/index.js +3 -0
- package/esm/pg-settings.js +6 -0
- package/index.d.ts +2 -2
- package/index.js +2 -1
- package/loaders/compute.d.ts +16 -0
- package/loaders/compute.js +60 -0
- package/loaders/create-loader.js +10 -1
- package/loaders/index.d.ts +1 -0
- package/loaders/index.js +5 -1
- package/package.json +3 -3
- package/pg-settings.js +6 -0
- package/types.d.ts +24 -0
package/esm/index.js
CHANGED
|
@@ -41,6 +41,6 @@ export { withPgClient } from './pg-client';
|
|
|
41
41
|
// Request ID middleware
|
|
42
42
|
export { requestIdMiddleware } from './request-id';
|
|
43
43
|
export { buildContext, createContextMiddleware } from './context';
|
|
44
|
-
export { agentChatLoader, authSettingsLoader, billingLoader, corsLoader, createDefaultRegistry, createLoaderRegistry, createModuleLoader, databaseSettingsLoader, inferenceLogLoader, pubkeyLoader, rlsLoader, llmLoader, webauthnLoader, } from './loaders';
|
|
44
|
+
export { agentChatLoader, authSettingsLoader, billingLoader, computeLoader, corsLoader, createDefaultRegistry, createLoaderRegistry, createModuleLoader, databaseSettingsLoader, inferenceLogLoader, pubkeyLoader, rlsLoader, llmLoader, webauthnLoader, } from './loaders';
|
|
45
45
|
// Side-effect: Express type augmentation
|
|
46
46
|
import './types';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute Module Loader
|
|
3
|
+
*
|
|
4
|
+
* Resolves per-database compute (functions) config from
|
|
5
|
+
* metaschema_modules_public.function_module and function_invocation_module.
|
|
6
|
+
* Returns the schema and table names for function definitions, API bindings,
|
|
7
|
+
* and invocations so REST routes can address the generated tables.
|
|
8
|
+
*
|
|
9
|
+
* Function modules are scoped: a database may provision one per scope, each
|
|
10
|
+
* with its own schema and tables. All of them are returned — REST routes and
|
|
11
|
+
* the GraphQL bindings plugin expose bindings from every module, and RLS on
|
|
12
|
+
* the underlying tables governs access.
|
|
13
|
+
*/
|
|
14
|
+
import { createModuleLoader } from './create-loader';
|
|
15
|
+
// ─── SQL ────────────────────────────────────────────────────────────────────
|
|
16
|
+
const COMPUTE_MODULE_SQL = `
|
|
17
|
+
SELECT
|
|
18
|
+
fs.schema_name AS functions_schema_name,
|
|
19
|
+
fm.definitions_table_name,
|
|
20
|
+
fm.bindings_table_name,
|
|
21
|
+
ivs.schema_name AS invocations_schema_name,
|
|
22
|
+
ivm.invocations_table_name,
|
|
23
|
+
ivm.entity_field AS invocations_entity_field
|
|
24
|
+
FROM metaschema_modules_public.function_module fm
|
|
25
|
+
JOIN metaschema_public.schema fs ON fs.id = fm.schema_id
|
|
26
|
+
JOIN metaschema_modules_public.function_invocation_module ivm
|
|
27
|
+
ON ivm.database_id = fm.database_id AND ivm.scope = fm.scope
|
|
28
|
+
JOIN metaschema_public.schema ivs ON ivs.id = ivm.schema_id
|
|
29
|
+
WHERE fm.database_id = $1
|
|
30
|
+
ORDER BY fs.schema_name
|
|
31
|
+
`;
|
|
32
|
+
// ─── Loader ─────────────────────────────────────────────────────────────────
|
|
33
|
+
export const computeLoader = createModuleLoader({
|
|
34
|
+
name: 'compute',
|
|
35
|
+
ttlMs: 60_000,
|
|
36
|
+
async resolve(ctx) {
|
|
37
|
+
const { tenantPool, databaseId } = ctx;
|
|
38
|
+
const result = await tenantPool.query(COMPUTE_MODULE_SQL, [databaseId]);
|
|
39
|
+
if (result.rows.length === 0)
|
|
40
|
+
return undefined;
|
|
41
|
+
return {
|
|
42
|
+
modules: result.rows.map((row) => ({
|
|
43
|
+
schemaName: row.functions_schema_name,
|
|
44
|
+
definitionsTableName: row.definitions_table_name,
|
|
45
|
+
// Physical bindings table name, recorded by the metaschema generator
|
|
46
|
+
// on the function_module config row — read as a fact, never derived
|
|
47
|
+
// from the definitions table name.
|
|
48
|
+
bindingsTableName: row.bindings_table_name,
|
|
49
|
+
invocationsSchemaName: row.invocations_schema_name,
|
|
50
|
+
invocationsTableName: row.invocations_table_name,
|
|
51
|
+
// Scope-key column of the invocations table (entity_field), or NULL
|
|
52
|
+
// for global scopes. Consumers set this column on inserts.
|
|
53
|
+
invocationsEntityField: row.invocations_entity_field,
|
|
54
|
+
})),
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
});
|
|
@@ -26,14 +26,23 @@ export function createModuleLoader(opts) {
|
|
|
26
26
|
return cache.get(key);
|
|
27
27
|
}
|
|
28
28
|
log.debug(`Cache MISS databaseId=${key}, resolving`);
|
|
29
|
+
// "Not provisioned" is expressed by the loader returning undefined, or
|
|
30
|
+
// by the module's tables not existing at all (42P01 undefined_table).
|
|
31
|
+
// Any other resolution error (bad query, ambiguous config) propagates —
|
|
32
|
+
// never silently coerced into "module absent".
|
|
29
33
|
try {
|
|
30
34
|
const value = await opts.resolve(ctx);
|
|
31
35
|
cache.set(key, value);
|
|
32
36
|
return value;
|
|
33
37
|
}
|
|
34
38
|
catch (e) {
|
|
39
|
+
if (e.code === '42P01') {
|
|
40
|
+
log.debug(`Module tables absent for databaseId=${key}: ${e.message}`);
|
|
41
|
+
cache.set(key, undefined);
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
35
44
|
log.warn(`Failed to resolve databaseId=${key}: ${e.message}`);
|
|
36
|
-
|
|
45
|
+
throw e;
|
|
37
46
|
}
|
|
38
47
|
},
|
|
39
48
|
invalidate(databaseId) {
|
package/esm/loaders/index.js
CHANGED
|
@@ -38,6 +38,7 @@ export { billingLoader } from './billing';
|
|
|
38
38
|
export { inferenceLogLoader } from './inference-log';
|
|
39
39
|
export { agentChatLoader } from './agent-chat';
|
|
40
40
|
export { llmLoader } from './llm';
|
|
41
|
+
export { computeLoader } from './compute';
|
|
41
42
|
/**
|
|
42
43
|
* Convenience: create a registry pre-loaded with all built-in loaders.
|
|
43
44
|
*/
|
|
@@ -52,6 +53,7 @@ import { billingLoader } from './billing';
|
|
|
52
53
|
import { inferenceLogLoader } from './inference-log';
|
|
53
54
|
import { agentChatLoader } from './agent-chat';
|
|
54
55
|
import { llmLoader } from './llm';
|
|
56
|
+
import { computeLoader } from './compute';
|
|
55
57
|
export function createDefaultRegistry() {
|
|
56
58
|
const registry = createLoaderRegistry();
|
|
57
59
|
registry.register(rlsLoader);
|
|
@@ -64,5 +66,6 @@ export function createDefaultRegistry() {
|
|
|
64
66
|
registry.register(inferenceLogLoader);
|
|
65
67
|
registry.register(agentChatLoader);
|
|
66
68
|
registry.register(llmLoader);
|
|
69
|
+
registry.register(computeLoader);
|
|
67
70
|
return registry;
|
|
68
71
|
}
|
package/esm/pg-settings.js
CHANGED
|
@@ -38,6 +38,12 @@ export function buildPgSettings(input) {
|
|
|
38
38
|
if (api.databaseId) {
|
|
39
39
|
settings['jwt.claims.database_id'] = api.databaseId;
|
|
40
40
|
}
|
|
41
|
+
// API provenance — which API surface this request arrived through.
|
|
42
|
+
// Derived server-side from hostname -> services_public.domains -> api_id;
|
|
43
|
+
// never taken from client-supplied headers, body, or token payload.
|
|
44
|
+
if (api.apiId) {
|
|
45
|
+
settings['jwt.claims.api_id'] = api.apiId;
|
|
46
|
+
}
|
|
41
47
|
// Distributed tracing
|
|
42
48
|
settings['request.id'] = requestId;
|
|
43
49
|
// Client metadata (for audit functions)
|
package/index.d.ts
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* });
|
|
35
35
|
* ```
|
|
36
36
|
*/
|
|
37
|
-
export type { AgentChatConfig, ApiConfigResult, ApiError, ApiModule, ApiStructure, AuthSettings, BillingConfig, BuiltinModuleMap, ConstructiveAPIToken, ConstructiveContext, CorsModuleData, DatabaseSettings, GenericModuleData, InferenceLogConfig, LlmConfig, PublicKeyChallengeData, PubkeyChallengeSettings, RlsModule, WebauthnSettings, WithPgClient, } from './types';
|
|
37
|
+
export type { AgentChatConfig, ApiConfigResult, ApiError, ApiModule, ApiStructure, AuthSettings, BillingConfig, BuiltinModuleMap, ComputeConfig, ComputeModuleConfig, ConstructiveAPIToken, ConstructiveContext, CorsModuleData, DatabaseSettings, GenericModuleData, InferenceLogConfig, LlmConfig, PublicKeyChallengeData, PubkeyChallengeSettings, RlsModule, WebauthnSettings, WithPgClient, } from './types';
|
|
38
38
|
export type { BillingClient, InferenceLogEntry } from './billing-client';
|
|
39
39
|
export { createBillingClient } from './billing-client';
|
|
40
40
|
export type { PgSettingsInput } from './pg-settings';
|
|
@@ -44,5 +44,5 @@ export { requestIdMiddleware } from './request-id';
|
|
|
44
44
|
export type { ContextMiddlewareOptions } from './context';
|
|
45
45
|
export { buildContext, createContextMiddleware } from './context';
|
|
46
46
|
export type { CreateLoaderOptions, LoaderContext, LoaderRegistry, ModuleLoader, } from './loaders';
|
|
47
|
-
export { agentChatLoader, authSettingsLoader, billingLoader, corsLoader, createDefaultRegistry, createLoaderRegistry, createModuleLoader, databaseSettingsLoader, inferenceLogLoader, pubkeyLoader, rlsLoader, llmLoader, webauthnLoader, } from './loaders';
|
|
47
|
+
export { agentChatLoader, authSettingsLoader, billingLoader, computeLoader, corsLoader, createDefaultRegistry, createLoaderRegistry, createModuleLoader, databaseSettingsLoader, inferenceLogLoader, pubkeyLoader, rlsLoader, llmLoader, webauthnLoader, } from './loaders';
|
|
48
48
|
import './types';
|
package/index.js
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
* ```
|
|
37
37
|
*/
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.webauthnLoader = exports.llmLoader = exports.rlsLoader = exports.pubkeyLoader = exports.inferenceLogLoader = exports.databaseSettingsLoader = exports.createModuleLoader = exports.createLoaderRegistry = exports.createDefaultRegistry = exports.corsLoader = exports.billingLoader = exports.authSettingsLoader = exports.agentChatLoader = exports.createContextMiddleware = exports.buildContext = exports.requestIdMiddleware = exports.withPgClient = exports.buildPgSettings = exports.createBillingClient = void 0;
|
|
39
|
+
exports.webauthnLoader = exports.llmLoader = exports.rlsLoader = exports.pubkeyLoader = exports.inferenceLogLoader = exports.databaseSettingsLoader = exports.createModuleLoader = exports.createLoaderRegistry = exports.createDefaultRegistry = exports.corsLoader = exports.computeLoader = exports.billingLoader = exports.authSettingsLoader = exports.agentChatLoader = exports.createContextMiddleware = exports.buildContext = exports.requestIdMiddleware = exports.withPgClient = exports.buildPgSettings = exports.createBillingClient = void 0;
|
|
40
40
|
var billing_client_1 = require("./billing-client");
|
|
41
41
|
Object.defineProperty(exports, "createBillingClient", { enumerable: true, get: function () { return billing_client_1.createBillingClient; } });
|
|
42
42
|
var pg_settings_1 = require("./pg-settings");
|
|
@@ -54,6 +54,7 @@ var loaders_1 = require("./loaders");
|
|
|
54
54
|
Object.defineProperty(exports, "agentChatLoader", { enumerable: true, get: function () { return loaders_1.agentChatLoader; } });
|
|
55
55
|
Object.defineProperty(exports, "authSettingsLoader", { enumerable: true, get: function () { return loaders_1.authSettingsLoader; } });
|
|
56
56
|
Object.defineProperty(exports, "billingLoader", { enumerable: true, get: function () { return loaders_1.billingLoader; } });
|
|
57
|
+
Object.defineProperty(exports, "computeLoader", { enumerable: true, get: function () { return loaders_1.computeLoader; } });
|
|
57
58
|
Object.defineProperty(exports, "corsLoader", { enumerable: true, get: function () { return loaders_1.corsLoader; } });
|
|
58
59
|
Object.defineProperty(exports, "createDefaultRegistry", { enumerable: true, get: function () { return loaders_1.createDefaultRegistry; } });
|
|
59
60
|
Object.defineProperty(exports, "createLoaderRegistry", { enumerable: true, get: function () { return loaders_1.createLoaderRegistry; } });
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute Module Loader
|
|
3
|
+
*
|
|
4
|
+
* Resolves per-database compute (functions) config from
|
|
5
|
+
* metaschema_modules_public.function_module and function_invocation_module.
|
|
6
|
+
* Returns the schema and table names for function definitions, API bindings,
|
|
7
|
+
* and invocations so REST routes can address the generated tables.
|
|
8
|
+
*
|
|
9
|
+
* Function modules are scoped: a database may provision one per scope, each
|
|
10
|
+
* with its own schema and tables. All of them are returned — REST routes and
|
|
11
|
+
* the GraphQL bindings plugin expose bindings from every module, and RLS on
|
|
12
|
+
* the underlying tables governs access.
|
|
13
|
+
*/
|
|
14
|
+
import type { ComputeConfig } from '../types';
|
|
15
|
+
import type { ModuleLoader } from './types';
|
|
16
|
+
export declare const computeLoader: ModuleLoader<ComputeConfig>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Compute Module Loader
|
|
4
|
+
*
|
|
5
|
+
* Resolves per-database compute (functions) config from
|
|
6
|
+
* metaschema_modules_public.function_module and function_invocation_module.
|
|
7
|
+
* Returns the schema and table names for function definitions, API bindings,
|
|
8
|
+
* and invocations so REST routes can address the generated tables.
|
|
9
|
+
*
|
|
10
|
+
* Function modules are scoped: a database may provision one per scope, each
|
|
11
|
+
* with its own schema and tables. All of them are returned — REST routes and
|
|
12
|
+
* the GraphQL bindings plugin expose bindings from every module, and RLS on
|
|
13
|
+
* the underlying tables governs access.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.computeLoader = void 0;
|
|
17
|
+
const create_loader_1 = require("./create-loader");
|
|
18
|
+
// ─── SQL ────────────────────────────────────────────────────────────────────
|
|
19
|
+
const COMPUTE_MODULE_SQL = `
|
|
20
|
+
SELECT
|
|
21
|
+
fs.schema_name AS functions_schema_name,
|
|
22
|
+
fm.definitions_table_name,
|
|
23
|
+
fm.bindings_table_name,
|
|
24
|
+
ivs.schema_name AS invocations_schema_name,
|
|
25
|
+
ivm.invocations_table_name,
|
|
26
|
+
ivm.entity_field AS invocations_entity_field
|
|
27
|
+
FROM metaschema_modules_public.function_module fm
|
|
28
|
+
JOIN metaschema_public.schema fs ON fs.id = fm.schema_id
|
|
29
|
+
JOIN metaschema_modules_public.function_invocation_module ivm
|
|
30
|
+
ON ivm.database_id = fm.database_id AND ivm.scope = fm.scope
|
|
31
|
+
JOIN metaschema_public.schema ivs ON ivs.id = ivm.schema_id
|
|
32
|
+
WHERE fm.database_id = $1
|
|
33
|
+
ORDER BY fs.schema_name
|
|
34
|
+
`;
|
|
35
|
+
// ─── Loader ─────────────────────────────────────────────────────────────────
|
|
36
|
+
exports.computeLoader = (0, create_loader_1.createModuleLoader)({
|
|
37
|
+
name: 'compute',
|
|
38
|
+
ttlMs: 60_000,
|
|
39
|
+
async resolve(ctx) {
|
|
40
|
+
const { tenantPool, databaseId } = ctx;
|
|
41
|
+
const result = await tenantPool.query(COMPUTE_MODULE_SQL, [databaseId]);
|
|
42
|
+
if (result.rows.length === 0)
|
|
43
|
+
return undefined;
|
|
44
|
+
return {
|
|
45
|
+
modules: result.rows.map((row) => ({
|
|
46
|
+
schemaName: row.functions_schema_name,
|
|
47
|
+
definitionsTableName: row.definitions_table_name,
|
|
48
|
+
// Physical bindings table name, recorded by the metaschema generator
|
|
49
|
+
// on the function_module config row — read as a fact, never derived
|
|
50
|
+
// from the definitions table name.
|
|
51
|
+
bindingsTableName: row.bindings_table_name,
|
|
52
|
+
invocationsSchemaName: row.invocations_schema_name,
|
|
53
|
+
invocationsTableName: row.invocations_table_name,
|
|
54
|
+
// Scope-key column of the invocations table (entity_field), or NULL
|
|
55
|
+
// for global scopes. Consumers set this column on inserts.
|
|
56
|
+
invocationsEntityField: row.invocations_entity_field,
|
|
57
|
+
})),
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
});
|
package/loaders/create-loader.js
CHANGED
|
@@ -29,14 +29,23 @@ function createModuleLoader(opts) {
|
|
|
29
29
|
return cache.get(key);
|
|
30
30
|
}
|
|
31
31
|
log.debug(`Cache MISS databaseId=${key}, resolving`);
|
|
32
|
+
// "Not provisioned" is expressed by the loader returning undefined, or
|
|
33
|
+
// by the module's tables not existing at all (42P01 undefined_table).
|
|
34
|
+
// Any other resolution error (bad query, ambiguous config) propagates —
|
|
35
|
+
// never silently coerced into "module absent".
|
|
32
36
|
try {
|
|
33
37
|
const value = await opts.resolve(ctx);
|
|
34
38
|
cache.set(key, value);
|
|
35
39
|
return value;
|
|
36
40
|
}
|
|
37
41
|
catch (e) {
|
|
42
|
+
if (e.code === '42P01') {
|
|
43
|
+
log.debug(`Module tables absent for databaseId=${key}: ${e.message}`);
|
|
44
|
+
cache.set(key, undefined);
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
38
47
|
log.warn(`Failed to resolve databaseId=${key}: ${e.message}`);
|
|
39
|
-
|
|
48
|
+
throw e;
|
|
40
49
|
}
|
|
41
50
|
},
|
|
42
51
|
invalidate(databaseId) {
|
package/loaders/index.d.ts
CHANGED
|
@@ -40,4 +40,5 @@ export { billingLoader } from './billing';
|
|
|
40
40
|
export { inferenceLogLoader } from './inference-log';
|
|
41
41
|
export { agentChatLoader } from './agent-chat';
|
|
42
42
|
export { llmLoader } from './llm';
|
|
43
|
+
export { computeLoader } from './compute';
|
|
43
44
|
export declare function createDefaultRegistry(): import("./registry").LoaderRegistry;
|
package/loaders/index.js
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* registry.register(myLoader);
|
|
28
28
|
*/
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
exports.llmLoader = exports.agentChatLoader = exports.inferenceLogLoader = exports.billingLoader = exports.authSettingsLoader = exports.webauthnLoader = exports.pubkeyLoader = exports.databaseSettingsLoader = exports.corsLoader = exports.rlsLoader = exports.createLoaderRegistry = exports.createModuleLoader = void 0;
|
|
30
|
+
exports.computeLoader = exports.llmLoader = exports.agentChatLoader = exports.inferenceLogLoader = exports.billingLoader = exports.authSettingsLoader = exports.webauthnLoader = exports.pubkeyLoader = exports.databaseSettingsLoader = exports.corsLoader = exports.rlsLoader = exports.createLoaderRegistry = exports.createModuleLoader = void 0;
|
|
31
31
|
exports.createDefaultRegistry = createDefaultRegistry;
|
|
32
32
|
var create_loader_1 = require("./create-loader");
|
|
33
33
|
Object.defineProperty(exports, "createModuleLoader", { enumerable: true, get: function () { return create_loader_1.createModuleLoader; } });
|
|
@@ -54,6 +54,8 @@ var agent_chat_1 = require("./agent-chat");
|
|
|
54
54
|
Object.defineProperty(exports, "agentChatLoader", { enumerable: true, get: function () { return agent_chat_1.agentChatLoader; } });
|
|
55
55
|
var llm_1 = require("./llm");
|
|
56
56
|
Object.defineProperty(exports, "llmLoader", { enumerable: true, get: function () { return llm_1.llmLoader; } });
|
|
57
|
+
var compute_1 = require("./compute");
|
|
58
|
+
Object.defineProperty(exports, "computeLoader", { enumerable: true, get: function () { return compute_1.computeLoader; } });
|
|
57
59
|
/**
|
|
58
60
|
* Convenience: create a registry pre-loaded with all built-in loaders.
|
|
59
61
|
*/
|
|
@@ -68,6 +70,7 @@ const billing_2 = require("./billing");
|
|
|
68
70
|
const inference_log_2 = require("./inference-log");
|
|
69
71
|
const agent_chat_2 = require("./agent-chat");
|
|
70
72
|
const llm_2 = require("./llm");
|
|
73
|
+
const compute_2 = require("./compute");
|
|
71
74
|
function createDefaultRegistry() {
|
|
72
75
|
const registry = (0, registry_2.createLoaderRegistry)();
|
|
73
76
|
registry.register(rls_2.rlsLoader);
|
|
@@ -80,5 +83,6 @@ function createDefaultRegistry() {
|
|
|
80
83
|
registry.register(inference_log_2.inferenceLogLoader);
|
|
81
84
|
registry.register(agent_chat_2.agentChatLoader);
|
|
82
85
|
registry.register(llm_2.llmLoader);
|
|
86
|
+
registry.register(compute_2.computeLoader);
|
|
83
87
|
return registry;
|
|
84
88
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constructive-io/express-context",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Extractable Express middleware for Constructive tenant context — domain resolution, JWT auth, pgSettings, and withPgClient",
|
|
5
5
|
"author": "Constructive <developers@constructive.io>",
|
|
6
6
|
"homepage": "https://github.com/constructive-io/constructive",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@constructive-io/url-domains": "^2.19.0",
|
|
33
33
|
"@pgpmjs/env": "^2.27.0",
|
|
34
34
|
"@pgpmjs/logger": "^2.14.0",
|
|
35
|
-
"@pgpmjs/server-utils": "^3.15.
|
|
35
|
+
"@pgpmjs/server-utils": "^3.15.1",
|
|
36
36
|
"@pgpmjs/types": "^2.34.0",
|
|
37
37
|
"lru-cache": "^11.2.7",
|
|
38
38
|
"pg": "^8.21.0",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"jwt",
|
|
60
60
|
"pgSettings"
|
|
61
61
|
],
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "cd21f62bb64bdc7f4f40f6cef6af73f8f1c8f8dc"
|
|
63
63
|
}
|
package/pg-settings.js
CHANGED
|
@@ -41,6 +41,12 @@ function buildPgSettings(input) {
|
|
|
41
41
|
if (api.databaseId) {
|
|
42
42
|
settings['jwt.claims.database_id'] = api.databaseId;
|
|
43
43
|
}
|
|
44
|
+
// API provenance — which API surface this request arrived through.
|
|
45
|
+
// Derived server-side from hostname -> services_public.domains -> api_id;
|
|
46
|
+
// never taken from client-supplied headers, body, or token payload.
|
|
47
|
+
if (api.apiId) {
|
|
48
|
+
settings['jwt.claims.api_id'] = api.apiId;
|
|
49
|
+
}
|
|
44
50
|
// Distributed tracing
|
|
45
51
|
settings['request.id'] = requestId;
|
|
46
52
|
// Client metadata (for audit functions)
|
package/types.d.ts
CHANGED
|
@@ -138,6 +138,29 @@ export interface AgentChatConfig {
|
|
|
138
138
|
messageTableName: string | null;
|
|
139
139
|
taskTableName: string | null;
|
|
140
140
|
}
|
|
141
|
+
/** One provisioned function-module scope's compute table names. */
|
|
142
|
+
export interface ComputeModuleConfig {
|
|
143
|
+
schemaName: string;
|
|
144
|
+
definitionsTableName: string;
|
|
145
|
+
bindingsTableName: string;
|
|
146
|
+
invocationsSchemaName: string;
|
|
147
|
+
invocationsTableName: string;
|
|
148
|
+
/**
|
|
149
|
+
* Scope-key column of the invocations table, read from the metaschema
|
|
150
|
+
* (`function_invocation_module.entity_field`): `database_id` for the
|
|
151
|
+
* database scope, `NULL` for global scopes (platform/app), or the entity
|
|
152
|
+
* key column for entity scopes. Consumers set this column on invocation
|
|
153
|
+
* inserts instead of switching on scope name.
|
|
154
|
+
*/
|
|
155
|
+
invocationsEntityField: string | null;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* All function modules provisioned on the database. A database may have one
|
|
159
|
+
* per scope; every module is exposed and RLS governs access to each.
|
|
160
|
+
*/
|
|
161
|
+
export interface ComputeConfig {
|
|
162
|
+
modules: ComputeModuleConfig[];
|
|
163
|
+
}
|
|
141
164
|
export interface LlmConfig {
|
|
142
165
|
embeddingProvider: string;
|
|
143
166
|
embeddingModel: string;
|
|
@@ -169,6 +192,7 @@ export interface BuiltinModuleMap {
|
|
|
169
192
|
inferenceLog: InferenceLogConfig;
|
|
170
193
|
agentChat: AgentChatConfig;
|
|
171
194
|
llm: LlmConfig;
|
|
195
|
+
compute: ComputeConfig;
|
|
172
196
|
}
|
|
173
197
|
/**
|
|
174
198
|
* Callback for executing queries within a tenant-scoped transaction
|