@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/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
- return hasData || hasStorage || hasProcesses;
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.processes exceed ${feature.max_bytes} bytes and will fail with HTTP 431`,
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,
@@ -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 interface FunctionServiceProcessesOptions {
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 url = `${origin(baseUrl)}${processes_contract_1.FUNCTION_PROCESS_READ_PATH}`;
79
- const { token, expiresAt } = readCredential({ request });
80
- async function read({ body, schema, }) {
81
- if (expiresAt <= Date.now() / 1000)
82
- throw new processes_contract_1.FunctionProcessReadError(401, 'expired_context', 'The process-read credential expired; start a new invocation');
83
- const parsed = processes_contract_1.functionProcessReadRequestSchema.parse(body);
84
- const response = await fetchImpl(url, {
85
- method: 'POST',
86
- headers: {
87
- 'content-type': 'application/json',
88
- [processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER]: token,
89
- },
90
- body: JSON.stringify(parsed),
91
- redirect: 'error',
92
- signal: AbortSignal.timeout(30_000),
93
- });
94
- const result = await response.json().catch(() => null);
95
- if (!response.ok) {
96
- const error = zod_1.z
97
- .object({
98
- code: zod_1.z.string().max(128).optional(),
99
- detail: zod_1.z.string().max(2000).optional(),
100
- })
101
- .safeParse(result);
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 url = `${origin(baseUrl)}${processes_contract_1.FUNCTION_PROCESS_READ_PATH}`;
17061
- const { token, expiresAt } = readCredential({ request });
17062
- async function read({ body, schema }) {
17063
- if (expiresAt <= Date.now() / 1e3)
17064
- throw new processes_contract_1.FunctionProcessReadError(401, "expired_context", "The process-read credential expired; start a new invocation");
17065
- const parsed = processes_contract_1.functionProcessReadRequestSchema.parse(body);
17066
- const response = await fetchImpl(url, {
17067
- method: "POST",
17068
- headers: {
17069
- "content-type": "application/json",
17070
- [processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER]: token
17071
- },
17072
- body: JSON.stringify(parsed),
17073
- redirect: "error",
17074
- signal: AbortSignal.timeout(3e4)
17075
- });
17076
- const result = await response.json().catch(() => null);
17077
- if (!response.ok) {
17078
- const error = zod_12.z.object({
17079
- code: zod_12.z.string().max(128).optional(),
17080
- detail: zod_12.z.string().max(2e3).optional()
17081
- }).safeParse(result);
17082
- throw new processes_contract_1.FunctionProcessReadError(response.status, error.success ? error.data.code ?? "process_read_failed" : "process_read_failed", error.success ? error.data.detail ?? "Process read failed" : "Process read failed");
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
- return hasData || hasStorage || hasProcesses;
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.processes exceed ${feature.max_bytes} bytes and will fail with HTTP 431`,
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.5",
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.5.0"
51
+ "@sequenceholdings/orm": "2.6.1"
52
52
  },
53
53
  "engines": {
54
54
  "node": ">=20"