@sequenceholdings/managed-functions 0.4.0 → 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 +70 -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/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/README.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# `@sequenceholdings/managed-functions`
|
|
2
2
|
|
|
3
|
+
## Group-member directory lookup (internal rollout)
|
|
4
|
+
|
|
5
|
+
Functions can resolve selected members of existing Atlas groups to active,
|
|
6
|
+
canonical user identities. This is an opt-in read capability, not a staff
|
|
7
|
+
registry, permission grant, arbitrary directory search, or authentication API.
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
capabilities:
|
|
11
|
+
directory:
|
|
12
|
+
groups: ["<existing-group-id>"]
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createFunctionDirectoryClient } from '@sequenceholdings/managed-functions'
|
|
17
|
+
|
|
18
|
+
const directory = createFunctionDirectoryClient({
|
|
19
|
+
baseUrl: process.env.ATLAS_ORIGIN!,
|
|
20
|
+
request: req,
|
|
21
|
+
})
|
|
22
|
+
const { members } = await directory.resolveMembers({
|
|
23
|
+
groupId,
|
|
24
|
+
subs: [selectedCanonicalSubject],
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Use `userIds` instead of `subs` to resolve row IDs selected from the existing
|
|
29
|
+
group picker; never submit both. Each call accepts 1–50 selectors. Missing,
|
|
30
|
+
disabled, tombstoned, wrong-tenant, or nonmember selections are omitted. Exact
|
|
31
|
+
subject lookup does not accept an email alias. For a save, require the selected
|
|
32
|
+
subject to appear exactly in the response; a failed request is not an empty
|
|
33
|
+
successful lookup. Historical display labels may retain inactive identities,
|
|
34
|
+
but cannot validate a new assignment.
|
|
35
|
+
|
|
36
|
+
Atlas supplies a dedicated five-minute `x-sequence-directory-token` only for
|
|
37
|
+
declared groups on direct human invocations. System runners and service accounts
|
|
38
|
+
are not supported. Each read rechecks current function invocation access,
|
|
39
|
+
active version, declared group scope, active caller, caller group visibility,
|
|
40
|
+
and active target identities inside the function's tenant. No service identity
|
|
41
|
+
widens the caller's directory visibility. The function still enforces its own
|
|
42
|
+
application action permissions. Validation is point-in-time, not atomic with
|
|
43
|
+
an application's later transaction.
|
|
44
|
+
|
|
45
|
+
Directory and process-read clients share the SDK's invocation transport and
|
|
46
|
+
`{ request, baseUrl, fetchImpl? }` options. Both accept Fetch `Headers` or Node
|
|
47
|
+
request headers (case-insensitively), reject duplicate credentials, check expiry
|
|
48
|
+
before each read, and validate responses. `FunctionDirectoryReadError` exposes
|
|
49
|
+
`status` and `code`, like `FunctionProcessReadError`; failures are never an empty
|
|
50
|
+
member list. Directory replies must contain only distinct requested identities.
|
|
51
|
+
Sharing transport does not share authority: process reads retain service-account
|
|
52
|
+
credentials, while directory reads retain their separate human-caller credential.
|
|
53
|
+
|
|
54
|
+
The internal SDK bridge is `POST /api/managed-functions/directory/members`;
|
|
55
|
+
ordinary Auth0 bearers, storage tokens and ORM tokens do not authenticate it.
|
|
56
|
+
Results are not cached; successful reads emit an audit event. The client never
|
|
57
|
+
follows redirects or forwards an unrelated credential. Allow the Atlas origin
|
|
58
|
+
in the function's existing egress policy. Reviewed Atlas/CLI and SDK releases
|
|
59
|
+
are required before consumers opt in (SDK 0.4.1+, CLI 0.5.2+, and Atlas
|
|
60
|
+
advertising `directory_members`). Preflight rejects absent/disabled support
|
|
61
|
+
and incompatible tooling before upload; older deployments do not supply the
|
|
62
|
+
header. This addition does not activate or redeploy any consumer. The existing
|
|
63
|
+
package root remains Preview/blocked on publication; the raw HTTP route is
|
|
64
|
+
internal, not a new public API contract.
|
|
65
|
+
|
|
66
|
+
Tenant deployments reuse `ATLAS_ARTIFACT_STUDIO_SIGNING_KEY`, already provided
|
|
67
|
+
by the OpCo secrets catalog for Managed Functions. Delegation uses a separate
|
|
68
|
+
HMAC domain, audience, environment, function version and invocation binding.
|
|
69
|
+
There are no new secrets, migrations, groups or grants. Missing signing
|
|
70
|
+
configuration fails closed, including local development.
|
|
71
|
+
|
|
72
|
+
|
|
3
73
|
`@sequenceholdings/managed-functions` is the TypeScript SDK for Managed
|
|
4
74
|
Functions. It provides caller-scoped ORM access, explicit service-account ORM
|
|
5
75
|
access, and opt-in caching. The
|
package/dist/capabilities.d.ts
CHANGED
|
@@ -13,6 +13,13 @@ export declare const MANAGED_FUNCTION_CAPABILITIES: {
|
|
|
13
13
|
};
|
|
14
14
|
};
|
|
15
15
|
readonly features: {
|
|
16
|
+
readonly directory_members: {
|
|
17
|
+
readonly field: "capabilities.directory.groups";
|
|
18
|
+
readonly supported: true;
|
|
19
|
+
readonly limit: "1 to 16 concrete groups; resolve 1 to 50 selected active members per call";
|
|
20
|
+
readonly min_cli: "0.5.2";
|
|
21
|
+
readonly min_sdk: "0.4.1";
|
|
22
|
+
};
|
|
16
23
|
readonly processes_read: {
|
|
17
24
|
readonly field: "capabilities.processes.read";
|
|
18
25
|
readonly supported: true;
|
|
@@ -57,6 +64,13 @@ export interface CapabilityTooling {
|
|
|
57
64
|
export interface ManagedFunctionCapabilities {
|
|
58
65
|
tooling: CapabilityTooling;
|
|
59
66
|
features: {
|
|
67
|
+
directory_members?: {
|
|
68
|
+
field: string;
|
|
69
|
+
supported: boolean;
|
|
70
|
+
limit: string;
|
|
71
|
+
min_cli: string;
|
|
72
|
+
min_sdk: string;
|
|
73
|
+
};
|
|
60
74
|
processes_read?: {
|
|
61
75
|
field: string;
|
|
62
76
|
supported: boolean;
|
|
@@ -108,6 +122,7 @@ export interface PreflightManifest {
|
|
|
108
122
|
data?: Readonly<Record<string, unknown>>;
|
|
109
123
|
storage?: unknown;
|
|
110
124
|
processes?: unknown;
|
|
125
|
+
directory?: unknown;
|
|
111
126
|
};
|
|
112
127
|
}
|
|
113
128
|
export interface PreflightIssue {
|
package/dist/capabilities.js
CHANGED
|
@@ -15,6 +15,13 @@ exports.MANAGED_FUNCTION_CAPABILITIES = {
|
|
|
15
15
|
sdk: { package: exports.MANAGED_FUNCTION_SDK_PACKAGE, min: '0.3.0' },
|
|
16
16
|
},
|
|
17
17
|
features: {
|
|
18
|
+
directory_members: {
|
|
19
|
+
field: 'capabilities.directory.groups',
|
|
20
|
+
supported: true,
|
|
21
|
+
limit: '1 to 16 concrete groups; resolve 1 to 50 selected active members per call',
|
|
22
|
+
min_cli: '0.5.2',
|
|
23
|
+
min_sdk: '0.4.1',
|
|
24
|
+
},
|
|
18
25
|
processes_read: {
|
|
19
26
|
field: 'capabilities.processes.read',
|
|
20
27
|
supported: true,
|
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { DIRECTORY_TOKEN_HEADER, directoryGroupIdSchema, directoryScopesSchema, directoryMembersInput, directoryMembersResponse, readDirectoryGroups } from './directory-config';
|
|
1
2
|
export { FUNCTION_PROCESS_TOKEN_HEADER, FUNCTION_PROCESS_READ_PATH, functionProcessReadScopesSchema, readFunctionProcessScopes, functionProcessReadRequestSchema, functionProcessRunSummarySchema } from './processes-contract';
|
|
2
3
|
export { shouldReportAtlasHttp } from './http-tracing';
|
|
3
4
|
import { z } from 'zod';
|
package/dist/config.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.cacheManifestSchema = exports.CACHE_MAX_TTL_SECONDS = exports.preflightManagedFunction = exports.parseDeployedPolicy = exports.versionIsOlder = exports.sdkVersionLowerBound = exports.sdkVersionFromPackageJson = exports.isPostgresEgress = exports.formatValidationDetail = exports.MANAGED_FUNCTION_SDK_PACKAGE = exports.MANAGED_FUNCTION_CLI_PACKAGE = exports.MANAGED_FUNCTION_CAPABILITIES = exports.managedFunctionWorkloadLimitsSchema = exports.MF_LIMITS_DEFAULTS = exports.MF_LIMITS_CAPS = exports.MANAGED_FUNCTION_LIMITS = exports.shouldReportAtlasHttp = exports.functionProcessRunSummarySchema = exports.functionProcessReadRequestSchema = exports.readFunctionProcessScopes = exports.functionProcessReadScopesSchema = exports.FUNCTION_PROCESS_READ_PATH = exports.FUNCTION_PROCESS_TOKEN_HEADER = void 0;
|
|
3
|
+
exports.cacheManifestSchema = exports.CACHE_MAX_TTL_SECONDS = exports.preflightManagedFunction = exports.parseDeployedPolicy = exports.versionIsOlder = exports.sdkVersionLowerBound = exports.sdkVersionFromPackageJson = exports.isPostgresEgress = exports.formatValidationDetail = exports.MANAGED_FUNCTION_SDK_PACKAGE = exports.MANAGED_FUNCTION_CLI_PACKAGE = exports.MANAGED_FUNCTION_CAPABILITIES = exports.managedFunctionWorkloadLimitsSchema = exports.MF_LIMITS_DEFAULTS = exports.MF_LIMITS_CAPS = exports.MANAGED_FUNCTION_LIMITS = exports.shouldReportAtlasHttp = exports.functionProcessRunSummarySchema = exports.functionProcessReadRequestSchema = exports.readFunctionProcessScopes = exports.functionProcessReadScopesSchema = exports.FUNCTION_PROCESS_READ_PATH = exports.FUNCTION_PROCESS_TOKEN_HEADER = exports.readDirectoryGroups = exports.directoryMembersResponse = exports.directoryMembersInput = exports.directoryScopesSchema = exports.directoryGroupIdSchema = exports.DIRECTORY_TOKEN_HEADER = void 0;
|
|
4
4
|
exports.readCacheConfiguration = readCacheConfiguration;
|
|
5
|
+
var directory_config_1 = require("./directory-config");
|
|
6
|
+
Object.defineProperty(exports, "DIRECTORY_TOKEN_HEADER", { enumerable: true, get: function () { return directory_config_1.DIRECTORY_TOKEN_HEADER; } });
|
|
7
|
+
Object.defineProperty(exports, "directoryGroupIdSchema", { enumerable: true, get: function () { return directory_config_1.directoryGroupIdSchema; } });
|
|
8
|
+
Object.defineProperty(exports, "directoryScopesSchema", { enumerable: true, get: function () { return directory_config_1.directoryScopesSchema; } });
|
|
9
|
+
Object.defineProperty(exports, "directoryMembersInput", { enumerable: true, get: function () { return directory_config_1.directoryMembersInput; } });
|
|
10
|
+
Object.defineProperty(exports, "directoryMembersResponse", { enumerable: true, get: function () { return directory_config_1.directoryMembersResponse; } });
|
|
11
|
+
Object.defineProperty(exports, "readDirectoryGroups", { enumerable: true, get: function () { return directory_config_1.readDirectoryGroups; } });
|
|
5
12
|
var processes_contract_1 = require("./processes-contract");
|
|
6
13
|
Object.defineProperty(exports, "FUNCTION_PROCESS_TOKEN_HEADER", { enumerable: true, get: function () { return processes_contract_1.FUNCTION_PROCESS_TOKEN_HEADER; } });
|
|
7
14
|
Object.defineProperty(exports, "FUNCTION_PROCESS_READ_PATH", { enumerable: true, get: function () { return processes_contract_1.FUNCTION_PROCESS_READ_PATH; } });
|
package/dist/deployed-policy.js
CHANGED
|
@@ -42,9 +42,23 @@ function normalizeCapabilities(value) {
|
|
|
42
42
|
http_headers: normalizeHeaders(features.http_headers),
|
|
43
43
|
invoke_timeout: normalizeTimeout(features.invoke_timeout),
|
|
44
44
|
processes_read: normalizeProcesses(features.processes_read),
|
|
45
|
+
directory_members: normalizeDirectory(features.directory_members),
|
|
45
46
|
},
|
|
46
47
|
};
|
|
47
48
|
}
|
|
49
|
+
function normalizeDirectory(value) {
|
|
50
|
+
if (!value || typeof value.supported !== 'boolean' || typeof value.limit !== 'string')
|
|
51
|
+
return undefined;
|
|
52
|
+
if (typeof value.min_cli !== 'string' || typeof value.min_sdk !== 'string')
|
|
53
|
+
return undefined;
|
|
54
|
+
return {
|
|
55
|
+
field: typeof value.field === 'string' ? value.field : 'capabilities.directory.groups',
|
|
56
|
+
supported: value.supported,
|
|
57
|
+
limit: value.limit,
|
|
58
|
+
min_cli: value.min_cli,
|
|
59
|
+
min_sdk: value.min_sdk,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
48
62
|
function normalizeProcesses(value) {
|
|
49
63
|
if (!value || typeof value.supported !== 'boolean' || typeof value.limit !== 'string')
|
|
50
64
|
return undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const DIRECTORY_TOKEN_HEADER = "x-sequence-directory-token";
|
|
3
|
+
export declare const directoryGroupIdSchema: z.ZodString;
|
|
4
|
+
export declare const directoryScopesSchema: z.ZodObject<{
|
|
5
|
+
groups: z.ZodArray<z.ZodString>;
|
|
6
|
+
}, z.core.$strict>;
|
|
7
|
+
export declare const directoryMembersInput: z.ZodUnion<readonly [z.ZodObject<{
|
|
8
|
+
groupId: z.ZodString;
|
|
9
|
+
userIds: z.ZodArray<z.ZodString>;
|
|
10
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
11
|
+
groupId: z.ZodString;
|
|
12
|
+
subs: z.ZodArray<z.ZodString>;
|
|
13
|
+
}, z.core.$strict>]>;
|
|
14
|
+
export declare const directoryMembersResponse: z.ZodObject<{
|
|
15
|
+
members: z.ZodArray<z.ZodObject<{
|
|
16
|
+
id: z.ZodString;
|
|
17
|
+
sub: z.ZodString;
|
|
18
|
+
name: z.ZodString;
|
|
19
|
+
email: z.ZodString;
|
|
20
|
+
deactivated: z.ZodLiteral<false>;
|
|
21
|
+
}, z.core.$strict>>;
|
|
22
|
+
}, z.core.$strict>;
|
|
23
|
+
export declare function readDirectoryGroups(manifest: unknown): string[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.directoryMembersResponse = exports.directoryMembersInput = exports.directoryScopesSchema = exports.directoryGroupIdSchema = exports.DIRECTORY_TOKEN_HEADER = void 0;
|
|
4
|
+
exports.readDirectoryGroups = readDirectoryGroups;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
exports.DIRECTORY_TOKEN_HEADER = 'x-sequence-directory-token';
|
|
7
|
+
exports.directoryGroupIdSchema = zod_1.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);
|
|
8
|
+
exports.directoryScopesSchema = zod_1.z.object({
|
|
9
|
+
groups: zod_1.z.array(exports.directoryGroupIdSchema).min(1).max(16),
|
|
10
|
+
}).strict();
|
|
11
|
+
const identity = zod_1.z.string().min(1).max(256).regex(/^[^\x00-\x1f\x7f]+$/);
|
|
12
|
+
exports.directoryMembersInput = zod_1.z.union([
|
|
13
|
+
zod_1.z.object({ groupId: exports.directoryGroupIdSchema, userIds: zod_1.z.array(identity).min(1).max(50) }).strict(),
|
|
14
|
+
zod_1.z.object({ groupId: exports.directoryGroupIdSchema, subs: zod_1.z.array(identity).min(1).max(50) }).strict(),
|
|
15
|
+
]);
|
|
16
|
+
exports.directoryMembersResponse = zod_1.z.object({ members: zod_1.z.array(zod_1.z.object({
|
|
17
|
+
id: zod_1.z.string(), sub: identity, name: zod_1.z.string(), email: zod_1.z.string(), deactivated: zod_1.z.literal(false),
|
|
18
|
+
}).strict()).max(50) }).strict();
|
|
19
|
+
function readDirectoryGroups(manifest) {
|
|
20
|
+
const parsed = zod_1.z.object({ capabilities: zod_1.z.object({ directory: exports.directoryScopesSchema.optional() }).optional() }).safeParse(manifest);
|
|
21
|
+
return parsed.success ? parsed.data.capabilities?.directory?.groups ?? [] : [];
|
|
22
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { directoryMembersInput, directoryMembersResponse } from './directory-config';
|
|
3
|
+
import { type FunctionInvocationClientOptions } from './invocation-client';
|
|
4
|
+
export type FunctionDirectoryOptions = FunctionInvocationClientOptions;
|
|
5
|
+
export type FunctionDirectoryMembersQuery = z.infer<typeof directoryMembersInput>;
|
|
6
|
+
export type FunctionDirectoryMembers = z.infer<typeof directoryMembersResponse>;
|
|
7
|
+
export interface FunctionDirectoryClient {
|
|
8
|
+
resolveMembers(input: FunctionDirectoryMembersQuery): Promise<FunctionDirectoryMembers>;
|
|
9
|
+
}
|
|
10
|
+
export declare class FunctionDirectoryReadError extends Error {
|
|
11
|
+
readonly status: number;
|
|
12
|
+
readonly code: string;
|
|
13
|
+
constructor(status: number, code: string, message: string);
|
|
14
|
+
}
|
|
15
|
+
export declare function createFunctionDirectoryClient({ request, baseUrl, fetchImpl, }: FunctionDirectoryOptions): FunctionDirectoryClient;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FunctionDirectoryReadError = void 0;
|
|
4
|
+
exports.createFunctionDirectoryClient = createFunctionDirectoryClient;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const directory_config_1 = require("./directory-config");
|
|
7
|
+
const invocation_client_1 = require("./invocation-client");
|
|
8
|
+
class FunctionDirectoryReadError extends Error {
|
|
9
|
+
status;
|
|
10
|
+
code;
|
|
11
|
+
constructor(status, code, message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.status = status;
|
|
14
|
+
this.code = code;
|
|
15
|
+
this.name = 'FunctionDirectoryReadError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.FunctionDirectoryReadError = FunctionDirectoryReadError;
|
|
19
|
+
function createFunctionDirectoryClient({ request, baseUrl, fetchImpl, }) {
|
|
20
|
+
const credential = (0, invocation_client_1.readInvocationCredential)({
|
|
21
|
+
request,
|
|
22
|
+
header: directory_config_1.DIRECTORY_TOKEN_HEADER,
|
|
23
|
+
maxBytes: 8192,
|
|
24
|
+
invalidContext: () => new FunctionDirectoryReadError(401, 'invalid_context', 'This invocation has no valid directory-read credential'),
|
|
25
|
+
claimsSchema: zod_1.z.object({
|
|
26
|
+
audience: zod_1.z.literal('atlas-function-group-directory-v1'),
|
|
27
|
+
sub: zod_1.z
|
|
28
|
+
.string()
|
|
29
|
+
.min(1)
|
|
30
|
+
.max(256)
|
|
31
|
+
.refine((sub) => sub.includes('|') &&
|
|
32
|
+
!sub.startsWith('service-account|') &&
|
|
33
|
+
!sub.endsWith('@clients')),
|
|
34
|
+
functionId: zod_1.z.string().min(1),
|
|
35
|
+
invocationId: zod_1.z.string().min(1),
|
|
36
|
+
exp: zod_1.z.number().int(),
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
39
|
+
const read = (0, invocation_client_1.createInvocationReadTransport)({
|
|
40
|
+
baseUrl,
|
|
41
|
+
fetchImpl,
|
|
42
|
+
path: '/api/managed-functions/directory/members',
|
|
43
|
+
header: directory_config_1.DIRECTORY_TOKEN_HEADER,
|
|
44
|
+
credential,
|
|
45
|
+
timeoutMs: 10_000,
|
|
46
|
+
error: (status, code, message) => new FunctionDirectoryReadError(status, code, message),
|
|
47
|
+
failure: {
|
|
48
|
+
code: 'directory_read_failed',
|
|
49
|
+
message: 'Directory read failed',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
async resolveMembers(input) {
|
|
54
|
+
const body = directory_config_1.directoryMembersInput.parse(input);
|
|
55
|
+
const result = await read({ body, schema: directory_config_1.directoryMembersResponse });
|
|
56
|
+
const selectors = new Set('userIds' in body ? body.userIds : body.subs);
|
|
57
|
+
const returned = result.members.map((member) => 'userIds' in body ? member.id : member.sub);
|
|
58
|
+
if (new Set(returned).size !== returned.length ||
|
|
59
|
+
returned.some((value) => !selectors.has(value))) {
|
|
60
|
+
throw new FunctionDirectoryReadError(502, 'malformed_response', 'Atlas returned duplicate or unrequested directory members');
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export { createFunctionDirectoryClient, FunctionDirectoryReadError } from './directory';
|
|
2
|
+
export type { FunctionDirectoryClient, FunctionDirectoryOptions, FunctionDirectoryMembers, FunctionDirectoryMembersQuery } from './directory';
|
|
3
|
+
export type { FunctionInvocationClientOptions } from './invocation-client';
|
|
1
4
|
export { createFunctionServiceProcessesClient, FunctionProcessReadError } from './processes';
|
|
2
5
|
export type { FunctionServiceProcessesClient, FunctionServiceProcessesOptions, FunctionProcessRunQuery, FunctionProcessRunSummary, FunctionProcessRunStatus, FunctionProcessRunsPage, FunctionProcessRunsPageQuery, FunctionProcessReadRequest } from './processes';
|
|
3
6
|
export { installFunctionTracing, runWithFunctionTracing } from './tracing';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.readCacheConfiguration = exports.cacheManifestSchema = exports.createCacheManager = exports.CacheError = exports.createFunctionStorageClient = exports.runWithFunctionTracing = exports.installFunctionTracing = exports.FunctionProcessReadError = exports.createFunctionServiceProcessesClient = void 0;
|
|
3
|
+
exports.readCacheConfiguration = exports.cacheManifestSchema = exports.createCacheManager = exports.CacheError = exports.createFunctionStorageClient = exports.runWithFunctionTracing = exports.installFunctionTracing = exports.FunctionProcessReadError = exports.createFunctionServiceProcessesClient = exports.FunctionDirectoryReadError = exports.createFunctionDirectoryClient = void 0;
|
|
4
4
|
exports.createManagedFunctionContext = createManagedFunctionContext;
|
|
5
|
+
var directory_1 = require("./directory");
|
|
6
|
+
Object.defineProperty(exports, "createFunctionDirectoryClient", { enumerable: true, get: function () { return directory_1.createFunctionDirectoryClient; } });
|
|
7
|
+
Object.defineProperty(exports, "FunctionDirectoryReadError", { enumerable: true, get: function () { return directory_1.FunctionDirectoryReadError; } });
|
|
5
8
|
var processes_1 = require("./processes");
|
|
6
9
|
Object.defineProperty(exports, "createFunctionServiceProcessesClient", { enumerable: true, get: function () { return processes_1.createFunctionServiceProcessesClient; } });
|
|
7
10
|
Object.defineProperty(exports, "FunctionProcessReadError", { enumerable: true, get: function () { return processes_1.FunctionProcessReadError; } });
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export interface FunctionInvocationClientOptions {
|
|
3
|
+
request: {
|
|
4
|
+
headers: Pick<Headers, 'get'> | Readonly<Record<string, string | readonly string[] | undefined>>;
|
|
5
|
+
};
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
fetchImpl?: typeof globalThis.fetch;
|
|
8
|
+
}
|
|
9
|
+
type ClientErrorFactory = (status: number, code: string, message: string) => Error;
|
|
10
|
+
export declare function readInvocationCredential<T extends {
|
|
11
|
+
exp: number;
|
|
12
|
+
}>({ request, header, maxBytes, claimsSchema, invalidContext, }: Pick<FunctionInvocationClientOptions, 'request'> & {
|
|
13
|
+
header: string;
|
|
14
|
+
maxBytes: number;
|
|
15
|
+
claimsSchema: z.ZodType<T>;
|
|
16
|
+
invalidContext: () => Error;
|
|
17
|
+
}): {
|
|
18
|
+
token: string;
|
|
19
|
+
expiresAt: number;
|
|
20
|
+
};
|
|
21
|
+
export declare function createInvocationReadTransport({ baseUrl, fetchImpl, path, header, credential, timeoutMs, error, failure, }: Pick<FunctionInvocationClientOptions, 'baseUrl' | 'fetchImpl'> & {
|
|
22
|
+
path: string;
|
|
23
|
+
header: string;
|
|
24
|
+
credential: {
|
|
25
|
+
token: string;
|
|
26
|
+
expiresAt: number;
|
|
27
|
+
};
|
|
28
|
+
timeoutMs: number;
|
|
29
|
+
error: ClientErrorFactory;
|
|
30
|
+
failure: {
|
|
31
|
+
code: string;
|
|
32
|
+
message: string;
|
|
33
|
+
};
|
|
34
|
+
}): <T>({ body, schema, }: {
|
|
35
|
+
body: unknown;
|
|
36
|
+
schema: z.ZodType<T>;
|
|
37
|
+
}) => Promise<T>;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readInvocationCredential = readInvocationCredential;
|
|
4
|
+
exports.createInvocationReadTransport = createInvocationReadTransport;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
function readInvocationCredential({ request, header, maxBytes, claimsSchema, invalidContext, }) {
|
|
7
|
+
const { headers } = request;
|
|
8
|
+
const matches = typeof headers.get === 'function'
|
|
9
|
+
? [headers.get(header)]
|
|
10
|
+
: Object.entries(headers)
|
|
11
|
+
.filter(([name]) => name.toLowerCase() === header)
|
|
12
|
+
.map(([, value]) => value);
|
|
13
|
+
const token = matches[0];
|
|
14
|
+
if (matches.length !== 1 ||
|
|
15
|
+
typeof token !== 'string' ||
|
|
16
|
+
token.length > maxBytes)
|
|
17
|
+
throw invalidContext();
|
|
18
|
+
const envelope = /^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]{43})$/.exec(token);
|
|
19
|
+
if (!envelope?.[1])
|
|
20
|
+
throw invalidContext();
|
|
21
|
+
let value;
|
|
22
|
+
try {
|
|
23
|
+
value = JSON.parse(Buffer.from(envelope[1], 'base64url').toString('utf8'));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
throw invalidContext();
|
|
27
|
+
}
|
|
28
|
+
const parsed = claimsSchema.safeParse(value);
|
|
29
|
+
if (!parsed.success)
|
|
30
|
+
throw invalidContext();
|
|
31
|
+
return { token, expiresAt: parsed.data.exp };
|
|
32
|
+
}
|
|
33
|
+
function trustedOrigin({ baseUrl, error, }) {
|
|
34
|
+
let url;
|
|
35
|
+
try {
|
|
36
|
+
url = new URL(baseUrl);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
throw error(400, 'invalid_configuration', 'Configure a trusted Atlas origin');
|
|
40
|
+
}
|
|
41
|
+
const loopback = url.protocol === 'http:' &&
|
|
42
|
+
['localhost', '127.0.0.1', '[::1]'].includes(url.hostname);
|
|
43
|
+
if ((!loopback && url.protocol !== 'https:') ||
|
|
44
|
+
url.username ||
|
|
45
|
+
url.password ||
|
|
46
|
+
url.pathname !== '/' ||
|
|
47
|
+
url.search ||
|
|
48
|
+
url.hash) {
|
|
49
|
+
throw error(400, 'invalid_configuration', 'Configure an HTTPS Atlas origin without credentials, path, query or fragment');
|
|
50
|
+
}
|
|
51
|
+
return url.origin;
|
|
52
|
+
}
|
|
53
|
+
const errorResponseSchema = zod_1.z.object({
|
|
54
|
+
code: zod_1.z.string().max(128).optional(),
|
|
55
|
+
detail: zod_1.z.string().max(2000).optional(),
|
|
56
|
+
});
|
|
57
|
+
function createInvocationReadTransport({ baseUrl, fetchImpl = globalThis.fetch, path, header, credential, timeoutMs, error, failure, }) {
|
|
58
|
+
const url = `${trustedOrigin({ baseUrl, error })}${path}`;
|
|
59
|
+
return async function read({ body, schema, }) {
|
|
60
|
+
if (credential.expiresAt <= Date.now() / 1000) {
|
|
61
|
+
throw error(401, 'expired_context', 'The invocation credential expired; start a new invocation');
|
|
62
|
+
}
|
|
63
|
+
const response = await fetchImpl(url, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: {
|
|
66
|
+
'content-type': 'application/json',
|
|
67
|
+
[header]: credential.token,
|
|
68
|
+
},
|
|
69
|
+
body: JSON.stringify(body),
|
|
70
|
+
redirect: 'error',
|
|
71
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
72
|
+
});
|
|
73
|
+
const result = await response.json().catch(() => null);
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
const parsed = errorResponseSchema.safeParse(result);
|
|
76
|
+
throw error(response.status, parsed.success ? (parsed.data.code ?? failure.code) : failure.code, parsed.success
|
|
77
|
+
? (parsed.data.detail ?? failure.message)
|
|
78
|
+
: failure.message);
|
|
79
|
+
}
|
|
80
|
+
const validated = schema.safeParse(result);
|
|
81
|
+
if (!validated.success)
|
|
82
|
+
throw error(502, 'malformed_response', 'Atlas returned an invalid capability response');
|
|
83
|
+
return validated.data;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type CapabilityTooling, type ManagedFunctionCapabilities, type PreflightIssue, type PreflightManifest } from './capabilities';
|
|
2
|
+
export declare function checkDirectory({ manifest, capabilities, tooling, cliVersion, sdkVersion, checkDeployment, issues, }: {
|
|
3
|
+
manifest: PreflightManifest;
|
|
4
|
+
capabilities: ManagedFunctionCapabilities | null;
|
|
5
|
+
tooling: CapabilityTooling;
|
|
6
|
+
cliVersion: string;
|
|
7
|
+
sdkVersion: string | null;
|
|
8
|
+
checkDeployment: boolean;
|
|
9
|
+
issues: PreflightIssue[];
|
|
10
|
+
}): void;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkDirectory = checkDirectory;
|
|
4
|
+
const capabilities_1 = require("./capabilities");
|
|
5
|
+
const preflight_issue_1 = require("./preflight-issue");
|
|
6
|
+
const directory_config_1 = require("./directory-config");
|
|
7
|
+
const sdk_range_1 = require("./sdk-range");
|
|
8
|
+
function checkDirectory({ manifest, capabilities, tooling, cliVersion, sdkVersion, checkDeployment, issues, }) {
|
|
9
|
+
const directory = manifest.capabilities?.directory;
|
|
10
|
+
if (directory === undefined)
|
|
11
|
+
return;
|
|
12
|
+
const deployed = capabilities?.features.directory_members;
|
|
13
|
+
const feature = deployed ?? capabilities_1.MANAGED_FUNCTION_CAPABILITIES.features.directory_members;
|
|
14
|
+
const details = {
|
|
15
|
+
limit: feature.limit, tooling, requiredCli: feature.min_cli,
|
|
16
|
+
requiredSdk: feature.min_sdk, cliVersion, sdkVersion,
|
|
17
|
+
};
|
|
18
|
+
const parsed = directory_config_1.directoryScopesSchema.safeParse(directory);
|
|
19
|
+
if (!parsed.success) {
|
|
20
|
+
issues.push((0, preflight_issue_1.createPreflightIssue)({
|
|
21
|
+
...details, field: 'capabilities.directory', problem: (0, capabilities_1.formatValidationDetail)(parsed.error.issues),
|
|
22
|
+
}));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (checkDeployment && deployed?.supported !== true) {
|
|
26
|
+
issues.push((0, preflight_issue_1.createPreflightIssue)({
|
|
27
|
+
...details, field: feature.field, problem: 'group-member directory reads are not supported by this deployment',
|
|
28
|
+
}));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if ((0, capabilities_1.versionIsOlder)(cliVersion, feature.min_cli) || (sdkVersion && (0, sdk_range_1.sdkConstraintIsOlder)(sdkVersion, feature.min_sdk))) {
|
|
32
|
+
issues.push((0, preflight_issue_1.createPreflightIssue)({
|
|
33
|
+
...details, field: feature.field, problem: 'the installed tooling does not support managed function group-member directory reads',
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
}
|
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.4.
|
|
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.6.
|
|
51
|
+
"@sequenceholdings/orm": "2.6.1"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=20"
|