@sequenceholdings/managed-functions 0.3.5 → 0.4.1
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/README.md +93 -0
- package/dist/capabilities.d.ts +15 -0
- package/dist/capabilities.js +7 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +8 -1
- package/dist/deployed-policy.js +14 -0
- package/dist/directory-config.d.ts +23 -0
- package/dist/directory-config.js +22 -0
- package/dist/directory.d.ts +15 -0
- package/dist/directory.js +65 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -1
- package/dist/invocation-client.d.ts +38 -0
- package/dist/invocation-client.js +85 -0
- package/dist/orm.d.ts +32 -4
- package/dist/orm.js +4 -3
- package/dist/preflight-directory.d.ts +10 -0
- package/dist/preflight-directory.js +36 -0
- package/dist/preflight.js +6 -2
- package/dist/processes.d.ts +2 -7
- package/dist/processes.js +25 -90
- package/dist/runtime.cjs +304 -73
- package/package.json +2 -2
package/dist/preflight.js
CHANGED
|
@@ -5,6 +5,8 @@ const capabilities_1 = require("./capabilities");
|
|
|
5
5
|
const sdk_range_1 = require("./sdk-range");
|
|
6
6
|
const preflight_issue_1 = require("./preflight-issue");
|
|
7
7
|
const preflight_processes_1 = require("./preflight-processes");
|
|
8
|
+
const preflight_directory_1 = require("./preflight-directory");
|
|
9
|
+
const directory_config_1 = require("./directory-config");
|
|
8
10
|
const processes_contract_1 = require("./processes-contract");
|
|
9
11
|
const WORKLOAD_FIELDS = [
|
|
10
12
|
'memory_mb',
|
|
@@ -21,6 +23,7 @@ function preflightManagedFunction({ manifest, limits, capabilities, cliVersion,
|
|
|
21
23
|
checkWorkload({ manifest, limits, tooling, cliVersion, sdkVersion, issues });
|
|
22
24
|
checkPostgres({ manifest, capabilities, tooling, cliVersion, sdkVersion, issues });
|
|
23
25
|
(0, preflight_processes_1.checkProcesses)({ manifest, capabilities, tooling, cliVersion, sdkVersion, checkDeployment, issues });
|
|
26
|
+
(0, preflight_directory_1.checkDirectory)({ manifest, capabilities, tooling, cliVersion, sdkVersion, checkDeployment, issues });
|
|
24
27
|
checkHeaders({ manifest, capabilities, tooling, cliVersion, sdkVersion, issues });
|
|
25
28
|
checkSdkTimeout({ manifest, limits, capabilities, tooling, cliVersion, sdkVersion, issues });
|
|
26
29
|
return issues;
|
|
@@ -122,7 +125,8 @@ function needsWideHeaders(manifest) {
|
|
|
122
125
|
const hasData = !!data && Object.keys(data).length > 0;
|
|
123
126
|
const hasStorage = !!storage && typeof storage === 'object' && Object.keys(storage).length > 0;
|
|
124
127
|
const hasProcesses = processes_contract_1.functionProcessReadScopesSchema.safeParse(manifest.capabilities?.processes).success;
|
|
125
|
-
|
|
128
|
+
const hasDirectory = directory_config_1.directoryScopesSchema.safeParse(manifest.capabilities?.directory).success;
|
|
129
|
+
return hasData || hasStorage || hasProcesses || hasDirectory;
|
|
126
130
|
}
|
|
127
131
|
function checkHeaders({ manifest, capabilities, tooling, cliVersion, sdkVersion, issues, }) {
|
|
128
132
|
const feature = capabilities?.features.http_headers;
|
|
@@ -133,7 +137,7 @@ function checkHeaders({ manifest, capabilities, tooling, cliVersion, sdkVersion,
|
|
|
133
137
|
return;
|
|
134
138
|
issues.push((0, preflight_issue_1.createPreflightIssue)({
|
|
135
139
|
field: feature.field,
|
|
136
|
-
problem: `invocation headers for capabilities.data, capabilities.storage, or capabilities.
|
|
140
|
+
problem: `invocation headers for capabilities.data, capabilities.storage, capabilities.processes, or capabilities.directory exceed ${feature.max_bytes} bytes and will fail with HTTP 431`,
|
|
137
141
|
limit: feature.limit,
|
|
138
142
|
tooling,
|
|
139
143
|
requiredCli: feature.min_cli,
|
package/dist/processes.d.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { type FunctionProcessRunQuery, type FunctionProcessRunSummary, type FunctionProcessRunsPage, type FunctionProcessRunsPageQuery } from './processes-contract';
|
|
2
|
+
import { type FunctionInvocationClientOptions } from './invocation-client';
|
|
2
3
|
export * from './processes-contract';
|
|
3
|
-
export
|
|
4
|
-
request: {
|
|
5
|
-
headers: Pick<Headers, 'get'> | Readonly<Record<string, string | readonly string[] | undefined>>;
|
|
6
|
-
};
|
|
7
|
-
baseUrl: string;
|
|
8
|
-
fetchImpl?: typeof globalThis.fetch;
|
|
9
|
-
}
|
|
4
|
+
export type FunctionServiceProcessesOptions = FunctionInvocationClientOptions;
|
|
10
5
|
export interface FunctionServiceProcessesClient {
|
|
11
6
|
getRun(query: FunctionProcessRunQuery): Promise<FunctionProcessRunSummary>;
|
|
12
7
|
listRunsPage(query: FunctionProcessRunsPageQuery): Promise<FunctionProcessRunsPage>;
|
package/dist/processes.js
CHANGED
|
@@ -17,99 +17,34 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
exports.createFunctionServiceProcessesClient = createFunctionServiceProcessesClient;
|
|
18
18
|
const zod_1 = require("zod");
|
|
19
19
|
const processes_contract_1 = require("./processes-contract");
|
|
20
|
+
const invocation_client_1 = require("./invocation-client");
|
|
20
21
|
__exportStar(require("./processes-contract"), exports);
|
|
21
22
|
const invalidContext = () => new processes_contract_1.FunctionProcessReadError(401, 'invalid_context', 'This invocation has no valid process-read credential');
|
|
22
|
-
function readCredential({ request, }) {
|
|
23
|
-
const { headers } = request;
|
|
24
|
-
const matches = typeof headers.get === 'function'
|
|
25
|
-
? [headers.get(processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER)]
|
|
26
|
-
: Object.entries(headers)
|
|
27
|
-
.filter(([name]) => name.toLowerCase() === processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER)
|
|
28
|
-
.map(([, value]) => value);
|
|
29
|
-
const token = matches[0];
|
|
30
|
-
if (matches.length !== 1 ||
|
|
31
|
-
typeof token !== 'string' ||
|
|
32
|
-
token.length > 16_384)
|
|
33
|
-
throw invalidContext();
|
|
34
|
-
const envelope = /^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]{43})$/.exec(token);
|
|
35
|
-
if (!envelope?.[1])
|
|
36
|
-
throw invalidContext();
|
|
37
|
-
let value;
|
|
38
|
-
try {
|
|
39
|
-
value = JSON.parse(Buffer.from(envelope[1], 'base64url').toString('utf8'));
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
throw invalidContext();
|
|
43
|
-
}
|
|
44
|
-
const parsed = zod_1.z
|
|
45
|
-
.object({
|
|
46
|
-
audience: zod_1.z.literal('atlas-managed-function-process-read'),
|
|
47
|
-
sub: zod_1.z.string().startsWith('service-account|'),
|
|
48
|
-
functionId: zod_1.z.string().min(1),
|
|
49
|
-
invocationId: zod_1.z.string().min(1),
|
|
50
|
-
exp: zod_1.z.number().int(),
|
|
51
|
-
})
|
|
52
|
-
.safeParse(value);
|
|
53
|
-
if (!parsed.success)
|
|
54
|
-
throw invalidContext();
|
|
55
|
-
return { token, expiresAt: parsed.data.exp };
|
|
56
|
-
}
|
|
57
|
-
function origin(baseUrl) {
|
|
58
|
-
let url;
|
|
59
|
-
try {
|
|
60
|
-
url = new URL(baseUrl);
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
throw new processes_contract_1.FunctionProcessReadError(400, 'invalid_configuration', 'Configure a trusted Atlas origin');
|
|
64
|
-
}
|
|
65
|
-
const loopback = url.protocol === 'http:' &&
|
|
66
|
-
['localhost', '127.0.0.1', '[::1]'].includes(url.hostname);
|
|
67
|
-
if ((!loopback && url.protocol !== 'https:') ||
|
|
68
|
-
url.username ||
|
|
69
|
-
url.password ||
|
|
70
|
-
url.pathname !== '/' ||
|
|
71
|
-
url.search ||
|
|
72
|
-
url.hash) {
|
|
73
|
-
throw new processes_contract_1.FunctionProcessReadError(400, 'invalid_configuration', 'Configure an HTTPS Atlas origin without credentials, path, query or fragment');
|
|
74
|
-
}
|
|
75
|
-
return url.origin;
|
|
76
|
-
}
|
|
77
23
|
function createFunctionServiceProcessesClient({ request, baseUrl, fetchImpl = globalThis.fetch, }) {
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
throw new processes_contract_1.FunctionProcessReadError(response.status, error.success
|
|
103
|
-
? (error.data.code ?? 'process_read_failed')
|
|
104
|
-
: 'process_read_failed', error.success
|
|
105
|
-
? (error.data.detail ?? 'Process read failed')
|
|
106
|
-
: 'Process read failed');
|
|
107
|
-
}
|
|
108
|
-
const validated = schema.safeParse(result);
|
|
109
|
-
if (!validated.success)
|
|
110
|
-
throw new processes_contract_1.FunctionProcessReadError(502, 'malformed_response', 'Atlas returned an invalid process-read response');
|
|
111
|
-
return validated.data;
|
|
112
|
-
}
|
|
24
|
+
const credential = (0, invocation_client_1.readInvocationCredential)({
|
|
25
|
+
request,
|
|
26
|
+
header: processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER,
|
|
27
|
+
maxBytes: 16_384,
|
|
28
|
+
invalidContext,
|
|
29
|
+
claimsSchema: zod_1.z.object({
|
|
30
|
+
audience: zod_1.z.literal('atlas-managed-function-process-read'),
|
|
31
|
+
sub: zod_1.z.string().startsWith('service-account|'),
|
|
32
|
+
functionId: zod_1.z.string().min(1),
|
|
33
|
+
invocationId: zod_1.z.string().min(1),
|
|
34
|
+
exp: zod_1.z.number().int(),
|
|
35
|
+
}),
|
|
36
|
+
});
|
|
37
|
+
const transport = (0, invocation_client_1.createInvocationReadTransport)({
|
|
38
|
+
baseUrl,
|
|
39
|
+
fetchImpl,
|
|
40
|
+
path: processes_contract_1.FUNCTION_PROCESS_READ_PATH,
|
|
41
|
+
header: processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER,
|
|
42
|
+
credential,
|
|
43
|
+
timeoutMs: 30_000,
|
|
44
|
+
error: (status, code, message) => new processes_contract_1.FunctionProcessReadError(status, code, message),
|
|
45
|
+
failure: { code: 'process_read_failed', message: 'Process read failed' },
|
|
46
|
+
});
|
|
47
|
+
const read = ({ body, schema }) => transport({ body: processes_contract_1.functionProcessReadRequestSchema.parse(body), schema });
|
|
113
48
|
return {
|
|
114
49
|
async getRun(query) {
|
|
115
50
|
const run = await read({
|
package/dist/runtime.cjs
CHANGED
|
@@ -16908,6 +16908,177 @@ var require_zod = __commonJS({
|
|
|
16908
16908
|
}
|
|
16909
16909
|
});
|
|
16910
16910
|
|
|
16911
|
+
// dist/directory-config.js
|
|
16912
|
+
var require_directory_config = __commonJS({
|
|
16913
|
+
"dist/directory-config.js"(exports2) {
|
|
16914
|
+
"use strict";
|
|
16915
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
16916
|
+
exports2.directoryMembersResponse = exports2.directoryMembersInput = exports2.directoryScopesSchema = exports2.directoryGroupIdSchema = exports2.DIRECTORY_TOKEN_HEADER = void 0;
|
|
16917
|
+
exports2.readDirectoryGroups = readDirectoryGroups;
|
|
16918
|
+
var zod_12 = require_zod();
|
|
16919
|
+
exports2.DIRECTORY_TOKEN_HEADER = "x-sequence-directory-token";
|
|
16920
|
+
exports2.directoryGroupIdSchema = zod_12.z.string().regex(/^(?:[a-f0-9]{24}|[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})$/i);
|
|
16921
|
+
exports2.directoryScopesSchema = zod_12.z.object({
|
|
16922
|
+
groups: zod_12.z.array(exports2.directoryGroupIdSchema).min(1).max(16)
|
|
16923
|
+
}).strict();
|
|
16924
|
+
var identity = zod_12.z.string().min(1).max(256).regex(/^[^\x00-\x1f\x7f]+$/);
|
|
16925
|
+
exports2.directoryMembersInput = zod_12.z.union([
|
|
16926
|
+
zod_12.z.object({ groupId: exports2.directoryGroupIdSchema, userIds: zod_12.z.array(identity).min(1).max(50) }).strict(),
|
|
16927
|
+
zod_12.z.object({ groupId: exports2.directoryGroupIdSchema, subs: zod_12.z.array(identity).min(1).max(50) }).strict()
|
|
16928
|
+
]);
|
|
16929
|
+
exports2.directoryMembersResponse = zod_12.z.object({ members: zod_12.z.array(zod_12.z.object({
|
|
16930
|
+
id: zod_12.z.string(),
|
|
16931
|
+
sub: identity,
|
|
16932
|
+
name: zod_12.z.string(),
|
|
16933
|
+
email: zod_12.z.string(),
|
|
16934
|
+
deactivated: zod_12.z.literal(false)
|
|
16935
|
+
}).strict()).max(50) }).strict();
|
|
16936
|
+
function readDirectoryGroups(manifest) {
|
|
16937
|
+
const parsed = zod_12.z.object({ capabilities: zod_12.z.object({ directory: exports2.directoryScopesSchema.optional() }).optional() }).safeParse(manifest);
|
|
16938
|
+
return parsed.success ? parsed.data.capabilities?.directory?.groups ?? [] : [];
|
|
16939
|
+
}
|
|
16940
|
+
}
|
|
16941
|
+
});
|
|
16942
|
+
|
|
16943
|
+
// dist/invocation-client.js
|
|
16944
|
+
var require_invocation_client = __commonJS({
|
|
16945
|
+
"dist/invocation-client.js"(exports2) {
|
|
16946
|
+
"use strict";
|
|
16947
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
16948
|
+
exports2.readInvocationCredential = readInvocationCredential;
|
|
16949
|
+
exports2.createInvocationReadTransport = createInvocationReadTransport;
|
|
16950
|
+
var zod_12 = require_zod();
|
|
16951
|
+
function readInvocationCredential({ request, header, maxBytes, claimsSchema, invalidContext }) {
|
|
16952
|
+
const { headers } = request;
|
|
16953
|
+
const matches = typeof headers.get === "function" ? [headers.get(header)] : Object.entries(headers).filter(([name]) => name.toLowerCase() === header).map(([, value2]) => value2);
|
|
16954
|
+
const token = matches[0];
|
|
16955
|
+
if (matches.length !== 1 || typeof token !== "string" || token.length > maxBytes)
|
|
16956
|
+
throw invalidContext();
|
|
16957
|
+
const envelope = /^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]{43})$/.exec(token);
|
|
16958
|
+
if (!envelope?.[1])
|
|
16959
|
+
throw invalidContext();
|
|
16960
|
+
let value;
|
|
16961
|
+
try {
|
|
16962
|
+
value = JSON.parse(Buffer.from(envelope[1], "base64url").toString("utf8"));
|
|
16963
|
+
} catch {
|
|
16964
|
+
throw invalidContext();
|
|
16965
|
+
}
|
|
16966
|
+
const parsed = claimsSchema.safeParse(value);
|
|
16967
|
+
if (!parsed.success)
|
|
16968
|
+
throw invalidContext();
|
|
16969
|
+
return { token, expiresAt: parsed.data.exp };
|
|
16970
|
+
}
|
|
16971
|
+
function trustedOrigin({ baseUrl, error }) {
|
|
16972
|
+
let url;
|
|
16973
|
+
try {
|
|
16974
|
+
url = new URL(baseUrl);
|
|
16975
|
+
} catch {
|
|
16976
|
+
throw error(400, "invalid_configuration", "Configure a trusted Atlas origin");
|
|
16977
|
+
}
|
|
16978
|
+
const loopback = url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
|
|
16979
|
+
if (!loopback && url.protocol !== "https:" || url.username || url.password || url.pathname !== "/" || url.search || url.hash) {
|
|
16980
|
+
throw error(400, "invalid_configuration", "Configure an HTTPS Atlas origin without credentials, path, query or fragment");
|
|
16981
|
+
}
|
|
16982
|
+
return url.origin;
|
|
16983
|
+
}
|
|
16984
|
+
var errorResponseSchema = zod_12.z.object({
|
|
16985
|
+
code: zod_12.z.string().max(128).optional(),
|
|
16986
|
+
detail: zod_12.z.string().max(2e3).optional()
|
|
16987
|
+
});
|
|
16988
|
+
function createInvocationReadTransport({ baseUrl, fetchImpl = globalThis.fetch, path, header, credential, timeoutMs, error, failure }) {
|
|
16989
|
+
const url = `${trustedOrigin({ baseUrl, error })}${path}`;
|
|
16990
|
+
return async function read({ body, schema }) {
|
|
16991
|
+
if (credential.expiresAt <= Date.now() / 1e3) {
|
|
16992
|
+
throw error(401, "expired_context", "The invocation credential expired; start a new invocation");
|
|
16993
|
+
}
|
|
16994
|
+
const response = await fetchImpl(url, {
|
|
16995
|
+
method: "POST",
|
|
16996
|
+
headers: {
|
|
16997
|
+
"content-type": "application/json",
|
|
16998
|
+
[header]: credential.token
|
|
16999
|
+
},
|
|
17000
|
+
body: JSON.stringify(body),
|
|
17001
|
+
redirect: "error",
|
|
17002
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
17003
|
+
});
|
|
17004
|
+
const result = await response.json().catch(() => null);
|
|
17005
|
+
if (!response.ok) {
|
|
17006
|
+
const parsed = errorResponseSchema.safeParse(result);
|
|
17007
|
+
throw error(response.status, parsed.success ? parsed.data.code ?? failure.code : failure.code, parsed.success ? parsed.data.detail ?? failure.message : failure.message);
|
|
17008
|
+
}
|
|
17009
|
+
const validated = schema.safeParse(result);
|
|
17010
|
+
if (!validated.success)
|
|
17011
|
+
throw error(502, "malformed_response", "Atlas returned an invalid capability response");
|
|
17012
|
+
return validated.data;
|
|
17013
|
+
};
|
|
17014
|
+
}
|
|
17015
|
+
}
|
|
17016
|
+
});
|
|
17017
|
+
|
|
17018
|
+
// dist/directory.js
|
|
17019
|
+
var require_directory = __commonJS({
|
|
17020
|
+
"dist/directory.js"(exports2) {
|
|
17021
|
+
"use strict";
|
|
17022
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
17023
|
+
exports2.FunctionDirectoryReadError = void 0;
|
|
17024
|
+
exports2.createFunctionDirectoryClient = createFunctionDirectoryClient;
|
|
17025
|
+
var zod_12 = require_zod();
|
|
17026
|
+
var directory_config_1 = require_directory_config();
|
|
17027
|
+
var invocation_client_1 = require_invocation_client();
|
|
17028
|
+
var FunctionDirectoryReadError = class extends Error {
|
|
17029
|
+
status;
|
|
17030
|
+
code;
|
|
17031
|
+
constructor(status, code, message) {
|
|
17032
|
+
super(message);
|
|
17033
|
+
this.status = status;
|
|
17034
|
+
this.code = code;
|
|
17035
|
+
this.name = "FunctionDirectoryReadError";
|
|
17036
|
+
}
|
|
17037
|
+
};
|
|
17038
|
+
exports2.FunctionDirectoryReadError = FunctionDirectoryReadError;
|
|
17039
|
+
function createFunctionDirectoryClient({ request, baseUrl, fetchImpl }) {
|
|
17040
|
+
const credential = (0, invocation_client_1.readInvocationCredential)({
|
|
17041
|
+
request,
|
|
17042
|
+
header: directory_config_1.DIRECTORY_TOKEN_HEADER,
|
|
17043
|
+
maxBytes: 8192,
|
|
17044
|
+
invalidContext: () => new FunctionDirectoryReadError(401, "invalid_context", "This invocation has no valid directory-read credential"),
|
|
17045
|
+
claimsSchema: zod_12.z.object({
|
|
17046
|
+
audience: zod_12.z.literal("atlas-function-group-directory-v1"),
|
|
17047
|
+
sub: zod_12.z.string().min(1).max(256).refine((sub) => sub.includes("|") && !sub.startsWith("service-account|") && !sub.endsWith("@clients")),
|
|
17048
|
+
functionId: zod_12.z.string().min(1),
|
|
17049
|
+
invocationId: zod_12.z.string().min(1),
|
|
17050
|
+
exp: zod_12.z.number().int()
|
|
17051
|
+
})
|
|
17052
|
+
});
|
|
17053
|
+
const read = (0, invocation_client_1.createInvocationReadTransport)({
|
|
17054
|
+
baseUrl,
|
|
17055
|
+
fetchImpl,
|
|
17056
|
+
path: "/api/managed-functions/directory/members",
|
|
17057
|
+
header: directory_config_1.DIRECTORY_TOKEN_HEADER,
|
|
17058
|
+
credential,
|
|
17059
|
+
timeoutMs: 1e4,
|
|
17060
|
+
error: (status, code, message) => new FunctionDirectoryReadError(status, code, message),
|
|
17061
|
+
failure: {
|
|
17062
|
+
code: "directory_read_failed",
|
|
17063
|
+
message: "Directory read failed"
|
|
17064
|
+
}
|
|
17065
|
+
});
|
|
17066
|
+
return {
|
|
17067
|
+
async resolveMembers(input) {
|
|
17068
|
+
const body = directory_config_1.directoryMembersInput.parse(input);
|
|
17069
|
+
const result = await read({ body, schema: directory_config_1.directoryMembersResponse });
|
|
17070
|
+
const selectors = new Set("userIds" in body ? body.userIds : body.subs);
|
|
17071
|
+
const returned = result.members.map((member) => "userIds" in body ? member.id : member.sub);
|
|
17072
|
+
if (new Set(returned).size !== returned.length || returned.some((value) => !selectors.has(value))) {
|
|
17073
|
+
throw new FunctionDirectoryReadError(502, "malformed_response", "Atlas returned duplicate or unrequested directory members");
|
|
17074
|
+
}
|
|
17075
|
+
return result;
|
|
17076
|
+
}
|
|
17077
|
+
};
|
|
17078
|
+
}
|
|
17079
|
+
}
|
|
17080
|
+
});
|
|
17081
|
+
|
|
16911
17082
|
// dist/processes-contract.js
|
|
16912
17083
|
var require_processes_contract = __commonJS({
|
|
16913
17084
|
"dist/processes-contract.js"(exports2) {
|
|
@@ -17015,77 +17186,34 @@ var require_processes = __commonJS({
|
|
|
17015
17186
|
exports2.createFunctionServiceProcessesClient = createFunctionServiceProcessesClient;
|
|
17016
17187
|
var zod_12 = require_zod();
|
|
17017
17188
|
var processes_contract_1 = require_processes_contract();
|
|
17189
|
+
var invocation_client_1 = require_invocation_client();
|
|
17018
17190
|
__exportStar(require_processes_contract(), exports2);
|
|
17019
17191
|
var invalidContext = () => new processes_contract_1.FunctionProcessReadError(401, "invalid_context", "This invocation has no valid process-read credential");
|
|
17020
|
-
function readCredential({ request }) {
|
|
17021
|
-
const { headers } = request;
|
|
17022
|
-
const matches = typeof headers.get === "function" ? [headers.get(processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER)] : Object.entries(headers).filter(([name]) => name.toLowerCase() === processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER).map(([, value2]) => value2);
|
|
17023
|
-
const token = matches[0];
|
|
17024
|
-
if (matches.length !== 1 || typeof token !== "string" || token.length > 16384)
|
|
17025
|
-
throw invalidContext();
|
|
17026
|
-
const envelope = /^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]{43})$/.exec(token);
|
|
17027
|
-
if (!envelope?.[1])
|
|
17028
|
-
throw invalidContext();
|
|
17029
|
-
let value;
|
|
17030
|
-
try {
|
|
17031
|
-
value = JSON.parse(Buffer.from(envelope[1], "base64url").toString("utf8"));
|
|
17032
|
-
} catch {
|
|
17033
|
-
throw invalidContext();
|
|
17034
|
-
}
|
|
17035
|
-
const parsed = zod_12.z.object({
|
|
17036
|
-
audience: zod_12.z.literal("atlas-managed-function-process-read"),
|
|
17037
|
-
sub: zod_12.z.string().startsWith("service-account|"),
|
|
17038
|
-
functionId: zod_12.z.string().min(1),
|
|
17039
|
-
invocationId: zod_12.z.string().min(1),
|
|
17040
|
-
exp: zod_12.z.number().int()
|
|
17041
|
-
}).safeParse(value);
|
|
17042
|
-
if (!parsed.success)
|
|
17043
|
-
throw invalidContext();
|
|
17044
|
-
return { token, expiresAt: parsed.data.exp };
|
|
17045
|
-
}
|
|
17046
|
-
function origin(baseUrl) {
|
|
17047
|
-
let url;
|
|
17048
|
-
try {
|
|
17049
|
-
url = new URL(baseUrl);
|
|
17050
|
-
} catch {
|
|
17051
|
-
throw new processes_contract_1.FunctionProcessReadError(400, "invalid_configuration", "Configure a trusted Atlas origin");
|
|
17052
|
-
}
|
|
17053
|
-
const loopback = url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
|
|
17054
|
-
if (!loopback && url.protocol !== "https:" || url.username || url.password || url.pathname !== "/" || url.search || url.hash) {
|
|
17055
|
-
throw new processes_contract_1.FunctionProcessReadError(400, "invalid_configuration", "Configure an HTTPS Atlas origin without credentials, path, query or fragment");
|
|
17056
|
-
}
|
|
17057
|
-
return url.origin;
|
|
17058
|
-
}
|
|
17059
17192
|
function createFunctionServiceProcessesClient({ request, baseUrl, fetchImpl = globalThis.fetch }) {
|
|
17060
|
-
const
|
|
17061
|
-
|
|
17062
|
-
|
|
17063
|
-
|
|
17064
|
-
|
|
17065
|
-
|
|
17066
|
-
|
|
17067
|
-
|
|
17068
|
-
|
|
17069
|
-
|
|
17070
|
-
|
|
17071
|
-
|
|
17072
|
-
|
|
17073
|
-
|
|
17074
|
-
|
|
17075
|
-
|
|
17076
|
-
|
|
17077
|
-
|
|
17078
|
-
|
|
17079
|
-
|
|
17080
|
-
|
|
17081
|
-
|
|
17082
|
-
|
|
17083
|
-
|
|
17084
|
-
const validated = schema.safeParse(result);
|
|
17085
|
-
if (!validated.success)
|
|
17086
|
-
throw new processes_contract_1.FunctionProcessReadError(502, "malformed_response", "Atlas returned an invalid process-read response");
|
|
17087
|
-
return validated.data;
|
|
17088
|
-
}
|
|
17193
|
+
const credential = (0, invocation_client_1.readInvocationCredential)({
|
|
17194
|
+
request,
|
|
17195
|
+
header: processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER,
|
|
17196
|
+
maxBytes: 16384,
|
|
17197
|
+
invalidContext,
|
|
17198
|
+
claimsSchema: zod_12.z.object({
|
|
17199
|
+
audience: zod_12.z.literal("atlas-managed-function-process-read"),
|
|
17200
|
+
sub: zod_12.z.string().startsWith("service-account|"),
|
|
17201
|
+
functionId: zod_12.z.string().min(1),
|
|
17202
|
+
invocationId: zod_12.z.string().min(1),
|
|
17203
|
+
exp: zod_12.z.number().int()
|
|
17204
|
+
})
|
|
17205
|
+
});
|
|
17206
|
+
const transport = (0, invocation_client_1.createInvocationReadTransport)({
|
|
17207
|
+
baseUrl,
|
|
17208
|
+
fetchImpl,
|
|
17209
|
+
path: processes_contract_1.FUNCTION_PROCESS_READ_PATH,
|
|
17210
|
+
header: processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER,
|
|
17211
|
+
credential,
|
|
17212
|
+
timeoutMs: 3e4,
|
|
17213
|
+
error: (status, code, message) => new processes_contract_1.FunctionProcessReadError(status, code, message),
|
|
17214
|
+
failure: { code: "process_read_failed", message: "Process read failed" }
|
|
17215
|
+
});
|
|
17216
|
+
const read = ({ body, schema }) => transport({ body: processes_contract_1.functionProcessReadRequestSchema.parse(body), schema });
|
|
17089
17217
|
return {
|
|
17090
17218
|
async getRun(query) {
|
|
17091
17219
|
const run = await read({
|
|
@@ -28185,6 +28313,13 @@ var require_capabilities = __commonJS({
|
|
|
28185
28313
|
sdk: { package: exports2.MANAGED_FUNCTION_SDK_PACKAGE, min: "0.3.0" }
|
|
28186
28314
|
},
|
|
28187
28315
|
features: {
|
|
28316
|
+
directory_members: {
|
|
28317
|
+
field: "capabilities.directory.groups",
|
|
28318
|
+
supported: true,
|
|
28319
|
+
limit: "1 to 16 concrete groups; resolve 1 to 50 selected active members per call",
|
|
28320
|
+
min_cli: "0.5.2",
|
|
28321
|
+
min_sdk: "0.4.1"
|
|
28322
|
+
},
|
|
28188
28323
|
processes_read: {
|
|
28189
28324
|
field: "capabilities.processes.read",
|
|
28190
28325
|
supported: true,
|
|
@@ -28316,10 +28451,24 @@ var require_deployed_policy = __commonJS({
|
|
|
28316
28451
|
postgres_egress: normalizePostgres(features.postgres_egress),
|
|
28317
28452
|
http_headers: normalizeHeaders(features.http_headers),
|
|
28318
28453
|
invoke_timeout: normalizeTimeout(features.invoke_timeout),
|
|
28319
|
-
processes_read: normalizeProcesses(features.processes_read)
|
|
28454
|
+
processes_read: normalizeProcesses(features.processes_read),
|
|
28455
|
+
directory_members: normalizeDirectory(features.directory_members)
|
|
28320
28456
|
}
|
|
28321
28457
|
};
|
|
28322
28458
|
}
|
|
28459
|
+
function normalizeDirectory(value) {
|
|
28460
|
+
if (!value || typeof value.supported !== "boolean" || typeof value.limit !== "string")
|
|
28461
|
+
return void 0;
|
|
28462
|
+
if (typeof value.min_cli !== "string" || typeof value.min_sdk !== "string")
|
|
28463
|
+
return void 0;
|
|
28464
|
+
return {
|
|
28465
|
+
field: typeof value.field === "string" ? value.field : "capabilities.directory.groups",
|
|
28466
|
+
supported: value.supported,
|
|
28467
|
+
limit: value.limit,
|
|
28468
|
+
min_cli: value.min_cli,
|
|
28469
|
+
min_sdk: value.min_sdk
|
|
28470
|
+
};
|
|
28471
|
+
}
|
|
28323
28472
|
function normalizeProcesses(value) {
|
|
28324
28473
|
if (!value || typeof value.supported !== "boolean" || typeof value.limit !== "string")
|
|
28325
28474
|
return void 0;
|
|
@@ -28449,6 +28598,58 @@ var require_preflight_processes = __commonJS({
|
|
|
28449
28598
|
}
|
|
28450
28599
|
});
|
|
28451
28600
|
|
|
28601
|
+
// dist/preflight-directory.js
|
|
28602
|
+
var require_preflight_directory = __commonJS({
|
|
28603
|
+
"dist/preflight-directory.js"(exports2) {
|
|
28604
|
+
"use strict";
|
|
28605
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
28606
|
+
exports2.checkDirectory = checkDirectory;
|
|
28607
|
+
var capabilities_1 = require_capabilities();
|
|
28608
|
+
var preflight_issue_1 = require_preflight_issue();
|
|
28609
|
+
var directory_config_1 = require_directory_config();
|
|
28610
|
+
var sdk_range_1 = require_sdk_range();
|
|
28611
|
+
function checkDirectory({ manifest, capabilities, tooling, cliVersion, sdkVersion, checkDeployment, issues }) {
|
|
28612
|
+
const directory = manifest.capabilities?.directory;
|
|
28613
|
+
if (directory === void 0)
|
|
28614
|
+
return;
|
|
28615
|
+
const deployed = capabilities?.features.directory_members;
|
|
28616
|
+
const feature = deployed ?? capabilities_1.MANAGED_FUNCTION_CAPABILITIES.features.directory_members;
|
|
28617
|
+
const details = {
|
|
28618
|
+
limit: feature.limit,
|
|
28619
|
+
tooling,
|
|
28620
|
+
requiredCli: feature.min_cli,
|
|
28621
|
+
requiredSdk: feature.min_sdk,
|
|
28622
|
+
cliVersion,
|
|
28623
|
+
sdkVersion
|
|
28624
|
+
};
|
|
28625
|
+
const parsed = directory_config_1.directoryScopesSchema.safeParse(directory);
|
|
28626
|
+
if (!parsed.success) {
|
|
28627
|
+
issues.push((0, preflight_issue_1.createPreflightIssue)({
|
|
28628
|
+
...details,
|
|
28629
|
+
field: "capabilities.directory",
|
|
28630
|
+
problem: (0, capabilities_1.formatValidationDetail)(parsed.error.issues)
|
|
28631
|
+
}));
|
|
28632
|
+
return;
|
|
28633
|
+
}
|
|
28634
|
+
if (checkDeployment && deployed?.supported !== true) {
|
|
28635
|
+
issues.push((0, preflight_issue_1.createPreflightIssue)({
|
|
28636
|
+
...details,
|
|
28637
|
+
field: feature.field,
|
|
28638
|
+
problem: "group-member directory reads are not supported by this deployment"
|
|
28639
|
+
}));
|
|
28640
|
+
return;
|
|
28641
|
+
}
|
|
28642
|
+
if ((0, capabilities_1.versionIsOlder)(cliVersion, feature.min_cli) || sdkVersion && (0, sdk_range_1.sdkConstraintIsOlder)(sdkVersion, feature.min_sdk)) {
|
|
28643
|
+
issues.push((0, preflight_issue_1.createPreflightIssue)({
|
|
28644
|
+
...details,
|
|
28645
|
+
field: feature.field,
|
|
28646
|
+
problem: "the installed tooling does not support managed function group-member directory reads"
|
|
28647
|
+
}));
|
|
28648
|
+
}
|
|
28649
|
+
}
|
|
28650
|
+
}
|
|
28651
|
+
});
|
|
28652
|
+
|
|
28452
28653
|
// dist/preflight.js
|
|
28453
28654
|
var require_preflight = __commonJS({
|
|
28454
28655
|
"dist/preflight.js"(exports2) {
|
|
@@ -28459,6 +28660,8 @@ var require_preflight = __commonJS({
|
|
|
28459
28660
|
var sdk_range_1 = require_sdk_range();
|
|
28460
28661
|
var preflight_issue_1 = require_preflight_issue();
|
|
28461
28662
|
var preflight_processes_1 = require_preflight_processes();
|
|
28663
|
+
var preflight_directory_1 = require_preflight_directory();
|
|
28664
|
+
var directory_config_1 = require_directory_config();
|
|
28462
28665
|
var processes_contract_1 = require_processes_contract();
|
|
28463
28666
|
var WORKLOAD_FIELDS = [
|
|
28464
28667
|
"memory_mb",
|
|
@@ -28475,6 +28678,7 @@ var require_preflight = __commonJS({
|
|
|
28475
28678
|
checkWorkload({ manifest, limits, tooling, cliVersion, sdkVersion, issues });
|
|
28476
28679
|
checkPostgres({ manifest, capabilities, tooling, cliVersion, sdkVersion, issues });
|
|
28477
28680
|
(0, preflight_processes_1.checkProcesses)({ manifest, capabilities, tooling, cliVersion, sdkVersion, checkDeployment, issues });
|
|
28681
|
+
(0, preflight_directory_1.checkDirectory)({ manifest, capabilities, tooling, cliVersion, sdkVersion, checkDeployment, issues });
|
|
28478
28682
|
checkHeaders({ manifest, capabilities, tooling, cliVersion, sdkVersion, issues });
|
|
28479
28683
|
checkSdkTimeout({ manifest, limits, capabilities, tooling, cliVersion, sdkVersion, issues });
|
|
28480
28684
|
return issues;
|
|
@@ -28576,7 +28780,8 @@ var require_preflight = __commonJS({
|
|
|
28576
28780
|
const hasData = !!data && Object.keys(data).length > 0;
|
|
28577
28781
|
const hasStorage = !!storage && typeof storage === "object" && Object.keys(storage).length > 0;
|
|
28578
28782
|
const hasProcesses = processes_contract_1.functionProcessReadScopesSchema.safeParse(manifest.capabilities?.processes).success;
|
|
28579
|
-
|
|
28783
|
+
const hasDirectory = directory_config_1.directoryScopesSchema.safeParse(manifest.capabilities?.directory).success;
|
|
28784
|
+
return hasData || hasStorage || hasProcesses || hasDirectory;
|
|
28580
28785
|
}
|
|
28581
28786
|
function checkHeaders({ manifest, capabilities, tooling, cliVersion, sdkVersion, issues }) {
|
|
28582
28787
|
const feature = capabilities?.features.http_headers;
|
|
@@ -28587,7 +28792,7 @@ var require_preflight = __commonJS({
|
|
|
28587
28792
|
return;
|
|
28588
28793
|
issues.push((0, preflight_issue_1.createPreflightIssue)({
|
|
28589
28794
|
field: feature.field,
|
|
28590
|
-
problem: `invocation headers for capabilities.data, capabilities.storage, or capabilities.
|
|
28795
|
+
problem: `invocation headers for capabilities.data, capabilities.storage, capabilities.processes, or capabilities.directory exceed ${feature.max_bytes} bytes and will fail with HTTP 431`,
|
|
28591
28796
|
limit: feature.limit,
|
|
28592
28797
|
tooling,
|
|
28593
28798
|
requiredCli: feature.min_cli,
|
|
@@ -28625,8 +28830,27 @@ var require_config2 = __commonJS({
|
|
|
28625
28830
|
"dist/config.js"(exports2) {
|
|
28626
28831
|
"use strict";
|
|
28627
28832
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
28628
|
-
exports2.cacheManifestSchema = exports2.CACHE_MAX_TTL_SECONDS = exports2.preflightManagedFunction = exports2.parseDeployedPolicy = exports2.versionIsOlder = exports2.sdkVersionLowerBound = exports2.sdkVersionFromPackageJson = exports2.isPostgresEgress = exports2.formatValidationDetail = exports2.MANAGED_FUNCTION_SDK_PACKAGE = exports2.MANAGED_FUNCTION_CLI_PACKAGE = exports2.MANAGED_FUNCTION_CAPABILITIES = exports2.managedFunctionWorkloadLimitsSchema = exports2.MF_LIMITS_DEFAULTS = exports2.MF_LIMITS_CAPS = exports2.MANAGED_FUNCTION_LIMITS = exports2.shouldReportAtlasHttp = exports2.functionProcessRunSummarySchema = exports2.functionProcessReadRequestSchema = exports2.readFunctionProcessScopes = exports2.functionProcessReadScopesSchema = exports2.FUNCTION_PROCESS_READ_PATH = exports2.FUNCTION_PROCESS_TOKEN_HEADER = void 0;
|
|
28833
|
+
exports2.cacheManifestSchema = exports2.CACHE_MAX_TTL_SECONDS = exports2.preflightManagedFunction = exports2.parseDeployedPolicy = exports2.versionIsOlder = exports2.sdkVersionLowerBound = exports2.sdkVersionFromPackageJson = exports2.isPostgresEgress = exports2.formatValidationDetail = exports2.MANAGED_FUNCTION_SDK_PACKAGE = exports2.MANAGED_FUNCTION_CLI_PACKAGE = exports2.MANAGED_FUNCTION_CAPABILITIES = exports2.managedFunctionWorkloadLimitsSchema = exports2.MF_LIMITS_DEFAULTS = exports2.MF_LIMITS_CAPS = exports2.MANAGED_FUNCTION_LIMITS = exports2.shouldReportAtlasHttp = exports2.functionProcessRunSummarySchema = exports2.functionProcessReadRequestSchema = exports2.readFunctionProcessScopes = exports2.functionProcessReadScopesSchema = exports2.FUNCTION_PROCESS_READ_PATH = exports2.FUNCTION_PROCESS_TOKEN_HEADER = exports2.readDirectoryGroups = exports2.directoryMembersResponse = exports2.directoryMembersInput = exports2.directoryScopesSchema = exports2.directoryGroupIdSchema = exports2.DIRECTORY_TOKEN_HEADER = void 0;
|
|
28629
28834
|
exports2.readCacheConfiguration = readCacheConfiguration;
|
|
28835
|
+
var directory_config_1 = require_directory_config();
|
|
28836
|
+
Object.defineProperty(exports2, "DIRECTORY_TOKEN_HEADER", { enumerable: true, get: function() {
|
|
28837
|
+
return directory_config_1.DIRECTORY_TOKEN_HEADER;
|
|
28838
|
+
} });
|
|
28839
|
+
Object.defineProperty(exports2, "directoryGroupIdSchema", { enumerable: true, get: function() {
|
|
28840
|
+
return directory_config_1.directoryGroupIdSchema;
|
|
28841
|
+
} });
|
|
28842
|
+
Object.defineProperty(exports2, "directoryScopesSchema", { enumerable: true, get: function() {
|
|
28843
|
+
return directory_config_1.directoryScopesSchema;
|
|
28844
|
+
} });
|
|
28845
|
+
Object.defineProperty(exports2, "directoryMembersInput", { enumerable: true, get: function() {
|
|
28846
|
+
return directory_config_1.directoryMembersInput;
|
|
28847
|
+
} });
|
|
28848
|
+
Object.defineProperty(exports2, "directoryMembersResponse", { enumerable: true, get: function() {
|
|
28849
|
+
return directory_config_1.directoryMembersResponse;
|
|
28850
|
+
} });
|
|
28851
|
+
Object.defineProperty(exports2, "readDirectoryGroups", { enumerable: true, get: function() {
|
|
28852
|
+
return directory_config_1.readDirectoryGroups;
|
|
28853
|
+
} });
|
|
28630
28854
|
var processes_contract_1 = require_processes_contract();
|
|
28631
28855
|
Object.defineProperty(exports2, "FUNCTION_PROCESS_TOKEN_HEADER", { enumerable: true, get: function() {
|
|
28632
28856
|
return processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER;
|
|
@@ -56959,8 +57183,15 @@ var require_valkey = __commonJS({
|
|
|
56959
57183
|
|
|
56960
57184
|
// dist/index.js
|
|
56961
57185
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56962
|
-
exports.readCacheConfiguration = exports.cacheManifestSchema = exports.createCacheManager = exports.CacheError = exports.createFunctionStorageClient = exports.runWithFunctionTracing = exports.installFunctionTracing = exports.FunctionProcessReadError = exports.createFunctionServiceProcessesClient = void 0;
|
|
57186
|
+
exports.readCacheConfiguration = exports.cacheManifestSchema = exports.createCacheManager = exports.CacheError = exports.createFunctionStorageClient = exports.runWithFunctionTracing = exports.installFunctionTracing = exports.FunctionProcessReadError = exports.createFunctionServiceProcessesClient = exports.FunctionDirectoryReadError = exports.createFunctionDirectoryClient = void 0;
|
|
56963
57187
|
exports.createManagedFunctionContext = createManagedFunctionContext;
|
|
57188
|
+
var directory_1 = require_directory();
|
|
57189
|
+
Object.defineProperty(exports, "createFunctionDirectoryClient", { enumerable: true, get: function() {
|
|
57190
|
+
return directory_1.createFunctionDirectoryClient;
|
|
57191
|
+
} });
|
|
57192
|
+
Object.defineProperty(exports, "FunctionDirectoryReadError", { enumerable: true, get: function() {
|
|
57193
|
+
return directory_1.FunctionDirectoryReadError;
|
|
57194
|
+
} });
|
|
56964
57195
|
var processes_1 = require_processes();
|
|
56965
57196
|
Object.defineProperty(exports, "createFunctionServiceProcessesClient", { enumerable: true, get: function() {
|
|
56966
57197
|
return processes_1.createFunctionServiceProcessesClient;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sequenceholdings/managed-functions",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Managed Function context and opt-in cache runtime",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"vitest": "^4.1.11",
|
|
49
49
|
"esbuild": "^0.25.0",
|
|
50
50
|
"tsup": "^8.3.0",
|
|
51
|
-
"@sequenceholdings/orm": "2.
|
|
51
|
+
"@sequenceholdings/orm": "2.6.1"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=20"
|