@sequenceholdings/artifact-studio 0.7.1 → 0.8.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 +87 -3
- package/dist/build.js +4 -2
- package/dist/gateway/authorization-cache.js +1 -1
- package/dist/gateway/control.d.ts +13 -1
- package/dist/gateway/control.js +3 -0
- package/dist/gateway/datadog-startup.d.ts +13 -0
- package/dist/gateway/datadog-startup.js +51 -0
- package/dist/gateway/hosted-proxy.d.ts +2 -0
- package/dist/gateway/hosted-proxy.js +9 -11
- package/dist/gateway/ingress-handler.js +2 -0
- package/dist/gateway/server.d.ts +1 -1
- package/dist/gateway/server.js +51 -20
- package/dist/gateway/session.d.ts +14 -0
- package/dist/gateway/session.js +31 -2
- package/dist/gateway-main.js +5 -3
- package/dist/manifest-next.d.ts +9 -0
- package/dist/manifest-next.js +5 -0
- package/dist/manifest.d.ts +3 -0
- package/dist/server/agent-responses.d.ts +425 -0
- package/dist/server/agent-responses.js +154 -0
- package/dist/server/broker-contract.d.ts +17 -0
- package/dist/server/broker-contract.js +17 -2
- package/dist/server/client.d.ts +5 -0
- package/dist/server/client.js +12 -2
- package/dist/server/groups.d.ts +32 -0
- package/dist/server/groups.js +28 -0
- package/dist/server/processes.d.ts +11 -0
- package/dist/server/request-authentication.d.ts +42 -0
- package/dist/server/request-authentication.js +93 -0
- package/dist/server/request-context.d.ts +1 -0
- package/dist/server/request-context.js +1 -0
- package/dist/server.d.ts +4 -3
- package/dist/server.js +2 -2
- package/dist/source-boundary.js +13 -5
- package/dist/templates/react-vite/package.json +1 -1
- package/dist/tunnel/broker.d.ts +14 -1
- package/dist/tunnel/broker.js +94 -10
- package/dist/tunnel/client.js +6 -0
- package/dist/tunnel/redis-types.d.ts +5 -1
- package/dist/tunnel/redis.d.ts +12 -0
- package/dist/tunnel/redis.js +102 -4
- package/dist/tunnel/transport.d.ts +3 -0
- package/package.json +2 -2
- package/templates/react-vite/package.json +1 -1
|
@@ -18,6 +18,10 @@ export declare function isArtifactApiPath(path: string): boolean;
|
|
|
18
18
|
export declare const ARTIFACT_PROCESS_RUN_STATUSES: readonly ["pending", "running", "completed", "failed", "cancelled", "timed_out"];
|
|
19
19
|
/** Lattice lists at most this many runs per call. */
|
|
20
20
|
export declare const ARTIFACT_PROCESS_RUNS_LIMIT = 500;
|
|
21
|
+
/** One page of the caller's own group memberships. */
|
|
22
|
+
export declare const ARTIFACT_GROUP_MEMBERSHIPS_LIMIT = 100;
|
|
23
|
+
/** How far a caller may page their own memberships. The directory is not walked past this. */
|
|
24
|
+
export declare const ARTIFACT_GROUP_MEMBERSHIPS_MAX_PAGE = 100;
|
|
21
25
|
/** A run page can filter to at most this many entities of one type. */
|
|
22
26
|
export declare const ARTIFACT_PROCESS_RUN_ENTITIES_LIMIT = 500;
|
|
23
27
|
/** A run share adds collaborators to at most this many explicitly assigned human nodes. */
|
|
@@ -105,6 +109,11 @@ export declare const artifactServerRequestSchema: z.ZodDiscriminatedUnion<[z.Zod
|
|
|
105
109
|
}>>;
|
|
106
110
|
process: z.ZodString;
|
|
107
111
|
runId: z.ZodOptional<z.ZodString>;
|
|
112
|
+
version: z.ZodOptional<z.ZodString>;
|
|
113
|
+
expectedProcess: z.ZodOptional<z.ZodObject<{
|
|
114
|
+
version: z.ZodString;
|
|
115
|
+
bundleHash: z.ZodString;
|
|
116
|
+
}, z.core.$strict>>;
|
|
108
117
|
startNodeId: z.ZodOptional<z.ZodString>;
|
|
109
118
|
title: z.ZodOptional<z.ZodString>;
|
|
110
119
|
entity: z.ZodOptional<z.ZodObject<{
|
|
@@ -298,6 +307,14 @@ export declare const artifactServerRequestSchema: z.ZodDiscriminatedUnion<[z.Zod
|
|
|
298
307
|
group: "group";
|
|
299
308
|
}>>>;
|
|
300
309
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
310
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
311
|
+
operation: z.ZodLiteral<"groups_memberships">;
|
|
312
|
+
mode: z.ZodDefault<z.ZodEnum<{
|
|
313
|
+
service: "service";
|
|
314
|
+
user: "user";
|
|
315
|
+
}>>;
|
|
316
|
+
page: z.ZodOptional<z.ZodNumber>;
|
|
317
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
301
318
|
}, z.core.$strict>, z.ZodObject<{
|
|
302
319
|
operation: z.ZodLiteral<"flags">;
|
|
303
320
|
mode: z.ZodDefault<z.ZodEnum<{
|
|
@@ -27,10 +27,16 @@ const id = z.string().min(1).max(255).regex(/^[a-zA-Z0-9_-]+$/);
|
|
|
27
27
|
const latticeId = z.string().min(2).max(128).regex(/^[A-Za-z0-9._-]+$/);
|
|
28
28
|
// A process version is the registry's own label (the bundle hash prefix today); FGA-safe class.
|
|
29
29
|
const latticeVersion = z.string().min(1).max(128).regex(/^[A-Za-z0-9._-]+$/);
|
|
30
|
+
// An assertion on the resolved immutable target, independent of the optional version selector.
|
|
31
|
+
const expectedProcessIdentity = z.object({ version: latticeVersion, bundleHash: z.string().regex(/^[a-f0-9]{64}$/) }).strict();
|
|
30
32
|
/** A Lattice run's lifecycle status, as `GET /api/lattice/runs` filters it. */
|
|
31
33
|
export const ARTIFACT_PROCESS_RUN_STATUSES = ['pending', 'running', 'completed', 'failed', 'cancelled', 'timed_out'];
|
|
32
34
|
/** Lattice lists at most this many runs per call. */
|
|
33
35
|
export const ARTIFACT_PROCESS_RUNS_LIMIT = 500;
|
|
36
|
+
/** One page of the caller's own group memberships. */
|
|
37
|
+
export const ARTIFACT_GROUP_MEMBERSHIPS_LIMIT = 100;
|
|
38
|
+
/** How far a caller may page their own memberships. The directory is not walked past this. */
|
|
39
|
+
export const ARTIFACT_GROUP_MEMBERSHIPS_MAX_PAGE = 100;
|
|
34
40
|
/** A run page can filter to at most this many entities of one type. */
|
|
35
41
|
export const ARTIFACT_PROCESS_RUN_ENTITIES_LIMIT = 500;
|
|
36
42
|
/** A run share adds collaborators to at most this many explicitly assigned human nodes. */
|
|
@@ -124,10 +130,12 @@ export const artifactServerRequestSchema = z.discriminatedUnion('operation', [
|
|
|
124
130
|
z.object({ operation: z.literal('function'), mode, id, params: z.record(z.string(), z.unknown()).optional() }).strict(),
|
|
125
131
|
// Starts a run of a declared process, as `POST /api/lattice/runs` does: the application names the
|
|
126
132
|
// run, passes its input, may seed who works each human node and may enter the graph at a node
|
|
127
|
-
// other than the process's start (the route's `start_node_id`).
|
|
128
|
-
// the
|
|
133
|
+
// other than the process's start (the route's `start_node_id`). A registered version may be
|
|
134
|
+
// selected explicitly; omitting it follows the active version. The engine stays server-owned.
|
|
129
135
|
z.object({
|
|
130
136
|
operation: z.literal('lattice'), mode, process: latticeId, runId: latticeId.optional(),
|
|
137
|
+
version: latticeVersion.optional(),
|
|
138
|
+
expectedProcess: expectedProcessIdentity.optional(),
|
|
131
139
|
startNodeId: z.string().min(1).max(255).regex(/^[A-Za-z0-9._-]+$/).optional(),
|
|
132
140
|
title: z.string().max(500).optional(),
|
|
133
141
|
entity: z.object({ type: entityRef, id: entityRef }).strict().optional(),
|
|
@@ -225,6 +233,13 @@ export const artifactServerRequestSchema = z.discriminatedUnion('operation', [
|
|
|
225
233
|
types: z.array(z.enum(ARTIFACT_PROCESS_PRINCIPAL_TYPES)).min(1).max(2).optional(),
|
|
226
234
|
limit: z.number().int().min(1).max(ARTIFACT_PROCESS_PRINCIPAL_SEARCH_LIMIT).optional(),
|
|
227
235
|
}).strict(),
|
|
236
|
+
// The signed-in user's own group memberships. No search, no admin directory, no group-id allowlist:
|
|
237
|
+
// the directory returns the groups this user is in. Service mode is refused by the handler.
|
|
238
|
+
z.object({
|
|
239
|
+
operation: z.literal('groups_memberships'), mode,
|
|
240
|
+
page: z.number().int().min(1).max(ARTIFACT_GROUP_MEMBERSHIPS_MAX_PAGE).optional(),
|
|
241
|
+
limit: z.number().int().min(1).max(ARTIFACT_GROUP_MEMBERSHIPS_LIMIT).optional(),
|
|
242
|
+
}).strict(),
|
|
228
243
|
// Evaluates feature flags as Atlas evaluates its own: for the user, or with no user in service mode.
|
|
229
244
|
// A read: it needs no manifest declaration, as the browser bridge's flags.isEnabled needs none.
|
|
230
245
|
z.object({ operation: z.literal('flags'), mode, names: z.array(flagName).min(1).max(ARTIFACT_FLAGS_PER_REQUEST) }).strict(),
|
package/dist/server/client.d.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { storageClient } from '@sequenceholdings/storage';
|
|
2
2
|
import { type OperationExecutor } from '@sequenceholdings/orm/client';
|
|
3
3
|
import { type ArtifactAuditAction, type ArtifactServerMode } from './broker-contract.js';
|
|
4
|
+
import { type ArtifactServerGroups } from './groups.js';
|
|
4
5
|
import { type ArtifactServerProcesses } from './processes.js';
|
|
5
6
|
import { type ArtifactOrmJsonScalars } from '../orm-json-scalars.js';
|
|
6
7
|
import { createArtifactLogger, type ArtifactLogRecord } from './logger.js';
|
|
7
8
|
import { type ArtifactRequestContext, type RequestContextV2External } from './request-context.js';
|
|
8
9
|
import { type ArtifactExternalAccept } from './external-context.js';
|
|
9
10
|
import { createApiClient } from './api-client.js';
|
|
11
|
+
import { type ArtifactServerAgents } from './agent-responses.js';
|
|
10
12
|
import { type ArtifactPrincipal } from './principal.js';
|
|
11
13
|
import { type ArtifactRuntimeConfig, type ArtifactRequestHeaders } from './runtime-config.js';
|
|
12
14
|
export { ArtifactPrincipalError, ArtifactServerError, INSUFFICIENT_USER_AUTHENTICATION, stepUpResponse } from './errors.js';
|
|
15
|
+
export type * from './groups.js';
|
|
13
16
|
export type * from './processes.js';
|
|
14
17
|
export type { ArtifactServerFetchOptions } from './api-client.js';
|
|
15
18
|
/**
|
|
@@ -77,11 +80,13 @@ export interface ArtifactServerClient<TContext extends ArtifactServerContext = A
|
|
|
77
80
|
mode: ArtifactServerMode;
|
|
78
81
|
log: ReturnType<typeof createArtifactLogger>;
|
|
79
82
|
api: ReturnType<typeof createApiClient>;
|
|
83
|
+
agents: ArtifactServerAgents;
|
|
80
84
|
storage: ReturnType<typeof storageClient>;
|
|
81
85
|
functions: {
|
|
82
86
|
invoke<TOutput = unknown>(id: string, params?: Record<string, unknown>): Promise<TOutput>;
|
|
83
87
|
};
|
|
84
88
|
processes: ArtifactServerProcesses;
|
|
89
|
+
groups: ArtifactServerGroups;
|
|
85
90
|
flags: ArtifactServerFlags;
|
|
86
91
|
audit: ArtifactServerAudit;
|
|
87
92
|
orm(input: ArtifactOrmOptions): OperationExecutor;
|
package/dist/server/client.js
CHANGED
|
@@ -3,6 +3,7 @@ import { StorageApiError, storageClient, storageErrorSchema } from '@sequencehol
|
|
|
3
3
|
import { OrmOperationError } from '@sequenceholdings/orm/client';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { artifactOrmIdempotencyKeySchema, artifactServerRequestSchema } from './broker-contract.js';
|
|
6
|
+
import { createArtifactGroupsClient } from './groups.js';
|
|
6
7
|
import { createArtifactProcessesClient } from './processes.js';
|
|
7
8
|
import { assertJsonScalarsAcknowledged, ORM_JSON_SCALARS_HEADER } from '../orm-json-scalars.js';
|
|
8
9
|
import { createArtifactLogger } from './logger.js';
|
|
@@ -10,6 +11,7 @@ import { ARTIFACT_REQUEST_CONTEXT_HEADER, ARTIFACT_RUNTIME_TOKEN_HEADER, ARTIFAC
|
|
|
10
11
|
import { verifyArtifactExternalContext } from './external-context.js';
|
|
11
12
|
import { isExternalContextToken } from './internal/signed-token.js';
|
|
12
13
|
import { createApiClient } from './api-client.js';
|
|
14
|
+
import { createArtifactAgentsClient } from './agent-responses.js';
|
|
13
15
|
import { pause, transientConnectionCode } from './connection-retry.js';
|
|
14
16
|
import { principalFromContext } from './principal.js';
|
|
15
17
|
import { artifactRuntimeConfigSchema, readArtifactRuntimeConfig } from './runtime-config.js';
|
|
@@ -51,7 +53,12 @@ export async function createArtifactServerClient({ headers, runtime, fetch: fetc
|
|
|
51
53
|
throw new ArtifactServerError(401, 'runtime_changed', 'Artifact runtime disconnected or changed; reload the preview');
|
|
52
54
|
return current;
|
|
53
55
|
};
|
|
54
|
-
|
|
56
|
+
// Opaque proof of the gateway's actual browser authentication. Atlas verifies it
|
|
57
|
+
// against this exact signed context; it grants nothing when copied to another request.
|
|
58
|
+
const authenticationToken = headers.get('x-sequence-artifact-authentication') ?? undefined;
|
|
59
|
+
if (authenticationToken !== undefined && authenticationToken.length > 4096)
|
|
60
|
+
throw new ArtifactServerError(401, 'invalid_request_context', 'Artifact gateway authentication proof exceeds its header limit');
|
|
61
|
+
return buildClient({ context, principal: principalFromContext(context), token, authenticationToken, getRuntime, fetcher, mode: 'user', logSink });
|
|
55
62
|
}
|
|
56
63
|
function buildClient(args) {
|
|
57
64
|
const { context, principal, mode, logSink } = args;
|
|
@@ -88,6 +95,7 @@ function buildClient(args) {
|
|
|
88
95
|
mode,
|
|
89
96
|
log,
|
|
90
97
|
api: createApiClient({ mode, request, json }),
|
|
98
|
+
agents: createArtifactAgentsClient({ mode, json }),
|
|
91
99
|
storage: storageClient({ request: (method, path, body) => storageJson(artifactServerRequestSchema.parse({ operation: 'storage', mode, method, path, body })) }),
|
|
92
100
|
functions: {
|
|
93
101
|
invoke: async (id, params) => {
|
|
@@ -96,6 +104,7 @@ function buildClient(args) {
|
|
|
96
104
|
},
|
|
97
105
|
},
|
|
98
106
|
processes: createArtifactProcessesClient({ mode, json }),
|
|
107
|
+
groups: createArtifactGroupsClient({ mode, json }),
|
|
99
108
|
flags: {
|
|
100
109
|
evaluate: evaluateFlags,
|
|
101
110
|
isEnabled: async (flagName) => (await evaluateFlags([flagName]))[flagName] === true,
|
|
@@ -211,7 +220,7 @@ function isReadOperation(operation) {
|
|
|
211
220
|
return false;
|
|
212
221
|
}
|
|
213
222
|
}
|
|
214
|
-
function createBrokerTransport({ context, principal, token, getRuntime, fetcher, log }) {
|
|
223
|
+
function createBrokerTransport({ context, principal, token, authenticationToken, getRuntime, fetcher, log }) {
|
|
215
224
|
const send = async (input, signal, stream = false) => {
|
|
216
225
|
// The one choke point for every broker operation: an external caller never acts as a user.
|
|
217
226
|
if (input.mode === 'user' && principal.kind === 'external')
|
|
@@ -239,6 +248,7 @@ function createBrokerTransport({ context, principal, token, getRuntime, fetcher,
|
|
|
239
248
|
'Content-Type': 'application/json',
|
|
240
249
|
[ARTIFACT_RUNTIME_TOKEN_HEADER]: runtime.sessionToken,
|
|
241
250
|
[ARTIFACT_REQUEST_CONTEXT_HEADER]: token,
|
|
251
|
+
...(authenticationToken !== undefined ? { 'x-sequence-artifact-authentication': authenticationToken } : {}),
|
|
242
252
|
},
|
|
243
253
|
body,
|
|
244
254
|
cache: 'no-store',
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ArtifactServerMode, type ArtifactServerRequest } from './broker-contract.js';
|
|
2
|
+
/** One group the signed-in user belongs to. `userRole` is `admin` when they administer it. */
|
|
3
|
+
export interface ArtifactGroupMembership {
|
|
4
|
+
id: string;
|
|
5
|
+
userRole: 'admin' | 'member';
|
|
6
|
+
memberCount: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ArtifactGroupMembershipsQuery {
|
|
9
|
+
page?: number;
|
|
10
|
+
limit?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ArtifactGroupMembershipsPage {
|
|
13
|
+
groups: ArtifactGroupMembership[];
|
|
14
|
+
pagination: {
|
|
15
|
+
page: number;
|
|
16
|
+
limit: number;
|
|
17
|
+
totalCount: number;
|
|
18
|
+
totalPages: number;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export interface ArtifactServerGroups {
|
|
22
|
+
/**
|
|
23
|
+
* The signed-in user's group memberships. Requires `server.capabilities.groups.read`.
|
|
24
|
+
* Atlas decides which groups they are in; this call cannot name groups, search the directory,
|
|
25
|
+
* or read another user's memberships.
|
|
26
|
+
*/
|
|
27
|
+
list(query?: ArtifactGroupMembershipsQuery): Promise<ArtifactGroupMembershipsPage>;
|
|
28
|
+
}
|
|
29
|
+
export declare function createArtifactGroupsClient({ mode, json }: {
|
|
30
|
+
mode: ArtifactServerMode;
|
|
31
|
+
json: (operation: ArtifactServerRequest) => Promise<unknown>;
|
|
32
|
+
}): ArtifactServerGroups;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ARTIFACT_GROUP_MEMBERSHIPS_LIMIT, artifactServerRequestSchema, } from './broker-contract.js';
|
|
3
|
+
import { ArtifactServerError } from './errors.js';
|
|
4
|
+
const membershipsPageSchema = z.object({
|
|
5
|
+
groups: z.array(z.object({
|
|
6
|
+
id: z.string().min(1).max(255),
|
|
7
|
+
userRole: z.enum(['admin', 'member']),
|
|
8
|
+
memberCount: z.number().int().nonnegative(),
|
|
9
|
+
}).strict()),
|
|
10
|
+
pagination: z.object({
|
|
11
|
+
page: z.number().int().min(1),
|
|
12
|
+
limit: z.number().int().min(1).max(ARTIFACT_GROUP_MEMBERSHIPS_LIMIT),
|
|
13
|
+
totalCount: z.number().int().nonnegative(),
|
|
14
|
+
totalPages: z.number().int().nonnegative(),
|
|
15
|
+
}).strict(),
|
|
16
|
+
}).strict();
|
|
17
|
+
export function createArtifactGroupsClient({ mode, json }) {
|
|
18
|
+
return {
|
|
19
|
+
async list(query = {}) {
|
|
20
|
+
const parsed = membershipsPageSchema.safeParse(await json(artifactServerRequestSchema.parse({
|
|
21
|
+
operation: 'groups_memberships', mode, ...query,
|
|
22
|
+
})));
|
|
23
|
+
if (!parsed.success)
|
|
24
|
+
throw new ArtifactServerError(502, 'invalid_response', 'Atlas returned a malformed groups response');
|
|
25
|
+
return parsed.data;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -7,6 +7,17 @@ export type { ArtifactProcessRunSharingAuthoritiesQuery, ArtifactProcessRunShari
|
|
|
7
7
|
/** A run of a process declared under `server.capabilities.processes.start`. */
|
|
8
8
|
export interface ArtifactProcessStart {
|
|
9
9
|
process: string;
|
|
10
|
+
/** Select a registered immutable version. Omit to start the process's current active version. */
|
|
11
|
+
version?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Require the resolved immutable target to match this version and bundle hash before Atlas
|
|
14
|
+
* creates the run. Drift returns 409 PROCESS_IDENTITY_MISMATCH; this assertion does not select
|
|
15
|
+
* a version. Use `version` separately to start a captured target after active-version promotion.
|
|
16
|
+
*/
|
|
17
|
+
expectedProcess?: {
|
|
18
|
+
version: string;
|
|
19
|
+
bundleHash: string;
|
|
20
|
+
};
|
|
10
21
|
/** Idempotency key: starting the same run id again returns the existing run. */
|
|
11
22
|
runId?: string;
|
|
12
23
|
/**
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type ArtifactGatewayPublicKeys, type ArtifactRequestContext } from './request-context.js';
|
|
2
|
+
export declare const ARTIFACT_REQUEST_AUTHENTICATION_HEADER = "x-sequence-artifact-authentication";
|
|
3
|
+
export declare const ARTIFACT_REQUEST_AUTHENTICATION_MAX_LENGTH = 4096;
|
|
4
|
+
export declare class ArtifactRequestHeaderError extends Error {
|
|
5
|
+
constructor();
|
|
6
|
+
}
|
|
7
|
+
/** Internal forwarding validation; the signed proof is verified by the receiving broker. */
|
|
8
|
+
export declare function validatedArtifactAuthenticationHeader({ token, contextToken, external }: {
|
|
9
|
+
token: unknown;
|
|
10
|
+
contextToken: unknown;
|
|
11
|
+
external?: boolean;
|
|
12
|
+
}): string | undefined;
|
|
13
|
+
/** Internal transport guard: trusted appended headers share the same 32 KiB transport budget. */
|
|
14
|
+
export declare function assertArtifactRequestHeaderBudget({ headers }: {
|
|
15
|
+
headers: Readonly<Record<string, string | string[]>>;
|
|
16
|
+
}): void;
|
|
17
|
+
/** Add only the gateway-controlled value after all browser-owned private headers were stripped. */
|
|
18
|
+
export declare function appendArtifactAuthenticationHeader({ headers, token, contextToken }: {
|
|
19
|
+
headers: Record<string, string | string[]>;
|
|
20
|
+
token: unknown;
|
|
21
|
+
contextToken: unknown;
|
|
22
|
+
}): void;
|
|
23
|
+
/** Cloud transport identity headers may come only from the platform's own credential provider. */
|
|
24
|
+
export declare function stripArtifactCloudHeaders({ headers }: {
|
|
25
|
+
headers: Record<string, string | string[]>;
|
|
26
|
+
}): void;
|
|
27
|
+
/**
|
|
28
|
+
* Verifies actual authentication separately from actor attribution. An absent proof keeps legacy
|
|
29
|
+
* contexts usable, but supplies no human authority. A present invalid proof always fails closed.
|
|
30
|
+
* The exact signed context bytes bind even bridge, deployment and service-account fields that
|
|
31
|
+
* are not repeated in this small proof. No application-authored context can supply this evidence.
|
|
32
|
+
*/
|
|
33
|
+
export declare function verifyArtifactRequestAuthentication({ token, requestContextToken, context, publicKeys, now }: {
|
|
34
|
+
token: string | null | undefined;
|
|
35
|
+
requestContextToken: string;
|
|
36
|
+
context: ArtifactRequestContext;
|
|
37
|
+
publicKeys: ArtifactGatewayPublicKeys;
|
|
38
|
+
now?: number;
|
|
39
|
+
}): Readonly<{
|
|
40
|
+
authenticationMethod: 'auth0_user';
|
|
41
|
+
sub: string;
|
|
42
|
+
}> | undefined;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { validateHeaderValue } from 'node:http';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { ArtifactContextError, artifactRequestContextSchema, verifyArtifactRequestContext } from './request-context.js';
|
|
5
|
+
import { ARTIFACT_EXTERNAL_CONTEXT_KID_PREFIX, verifySignedContext } from './internal/signed-token.js';
|
|
6
|
+
export const ARTIFACT_REQUEST_AUTHENTICATION_HEADER = 'x-sequence-artifact-authentication';
|
|
7
|
+
export const ARTIFACT_REQUEST_AUTHENTICATION_MAX_LENGTH = 4096;
|
|
8
|
+
export class ArtifactRequestHeaderError extends Error {
|
|
9
|
+
constructor() { super('Artifact request headers exceed the transport limit'); this.name = 'ArtifactRequestHeaderError'; }
|
|
10
|
+
}
|
|
11
|
+
/** Internal forwarding validation; the signed proof is verified by the receiving broker. */
|
|
12
|
+
export function validatedArtifactAuthenticationHeader({ token, contextToken, external = false }) {
|
|
13
|
+
if (token === undefined)
|
|
14
|
+
return undefined;
|
|
15
|
+
if (typeof token !== 'string' || !token || token.length > ARTIFACT_REQUEST_AUTHENTICATION_MAX_LENGTH ||
|
|
16
|
+
typeof contextToken !== 'string' || !contextToken || external)
|
|
17
|
+
throw new Error('Invalid Artifact request authentication');
|
|
18
|
+
validateHeaderValue(ARTIFACT_REQUEST_AUTHENTICATION_HEADER, token);
|
|
19
|
+
return token;
|
|
20
|
+
}
|
|
21
|
+
/** Internal transport guard: trusted appended headers share the same 32 KiB transport budget. */
|
|
22
|
+
export function assertArtifactRequestHeaderBudget({ headers }) {
|
|
23
|
+
let bytes = 0;
|
|
24
|
+
const entries = Object.entries(headers);
|
|
25
|
+
if (entries.length > 128)
|
|
26
|
+
throw new ArtifactRequestHeaderError();
|
|
27
|
+
for (const [name, value] of entries) {
|
|
28
|
+
// Node may emit array values as repeated lines. Counting each name/CRLF is conservative
|
|
29
|
+
// even for cookie values, which Node joins instead of repeating.
|
|
30
|
+
for (const item of Array.isArray(value) ? value : [value]) {
|
|
31
|
+
bytes += Buffer.byteLength(name) + Buffer.byteLength(item) + 4;
|
|
32
|
+
if (bytes > 32 * 1024)
|
|
33
|
+
throw new ArtifactRequestHeaderError();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Add only the gateway-controlled value after all browser-owned private headers were stripped. */
|
|
38
|
+
export function appendArtifactAuthenticationHeader({ headers, token, contextToken }) {
|
|
39
|
+
const authentication = validatedArtifactAuthenticationHeader({ token, contextToken });
|
|
40
|
+
if (authentication !== undefined)
|
|
41
|
+
headers[ARTIFACT_REQUEST_AUTHENTICATION_HEADER] = authentication;
|
|
42
|
+
assertArtifactRequestHeaderBudget({ headers });
|
|
43
|
+
}
|
|
44
|
+
/** Cloud transport identity headers may come only from the platform's own credential provider. */
|
|
45
|
+
export function stripArtifactCloudHeaders({ headers }) {
|
|
46
|
+
for (const name of Object.keys(headers)) {
|
|
47
|
+
if (name === 'x-serverless-authorization' || name.startsWith('x-goog-'))
|
|
48
|
+
delete headers[name];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Internal signed format. Authentication is deliberately absent from the public v1 context. */
|
|
52
|
+
const authenticationProofSchema = z.object({
|
|
53
|
+
purpose: z.literal('artifact-request-authentication'), v: z.literal(1),
|
|
54
|
+
iss: z.literal('atlas-artifact-gateway'), aud: z.string().min(1).max(300),
|
|
55
|
+
authenticationMethod: z.literal('auth0_user'), sub: z.string().min(1).max(255),
|
|
56
|
+
contextJti: z.uuid(), contextSha256: z.string().regex(/^[a-f0-9]{64}$/),
|
|
57
|
+
projectId: z.string().min(1).max(255), environment: z.string().min(1).max(255),
|
|
58
|
+
method: z.enum(['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']), pathSha256: z.string().regex(/^[a-f0-9]{64}$/),
|
|
59
|
+
iat: z.number().int().nonnegative(), exp: z.number().int().positive(),
|
|
60
|
+
}).strict();
|
|
61
|
+
/**
|
|
62
|
+
* Verifies actual authentication separately from actor attribution. An absent proof keeps legacy
|
|
63
|
+
* contexts usable, but supplies no human authority. A present invalid proof always fails closed.
|
|
64
|
+
* The exact signed context bytes bind even bridge, deployment and service-account fields that
|
|
65
|
+
* are not repeated in this small proof. No application-authored context can supply this evidence.
|
|
66
|
+
*/
|
|
67
|
+
export function verifyArtifactRequestAuthentication({ token, requestContextToken, context, publicKeys, now = Math.floor(Date.now() / 1000) }) {
|
|
68
|
+
if (token === null || token === undefined)
|
|
69
|
+
return undefined;
|
|
70
|
+
try {
|
|
71
|
+
if (!token || token.length > ARTIFACT_REQUEST_AUTHENTICATION_MAX_LENGTH)
|
|
72
|
+
throw new ArtifactContextError();
|
|
73
|
+
const signedContext = verifyArtifactRequestContext({ token: requestContextToken, publicKeys,
|
|
74
|
+
projectId: context.projectId, environment: context.environment, method: context.method, path: context.path, now });
|
|
75
|
+
if (JSON.stringify(signedContext) !== JSON.stringify(artifactRequestContextSchema.parse(context)))
|
|
76
|
+
throw new ArtifactContextError();
|
|
77
|
+
const contextSignature = verifySignedContext({ token: requestContextToken, publicKeys });
|
|
78
|
+
const verified = verifySignedContext({ token, publicKeys });
|
|
79
|
+
if (verified.kid.startsWith(ARTIFACT_EXTERNAL_CONTEXT_KID_PREFIX) || verified.kid !== contextSignature.kid)
|
|
80
|
+
throw new ArtifactContextError();
|
|
81
|
+
const proof = authenticationProofSchema.parse(verified.payload);
|
|
82
|
+
if (proof.contextSha256 !== createHash('sha256').update(requestContextToken).digest('hex') ||
|
|
83
|
+
proof.contextJti !== signedContext.jti || proof.sub !== signedContext.sub || proof.aud !== signedContext.aud ||
|
|
84
|
+
proof.projectId !== signedContext.projectId || proof.environment !== signedContext.environment ||
|
|
85
|
+
proof.method !== signedContext.method || proof.pathSha256 !== createHash('sha256').update(signedContext.path).digest('hex') ||
|
|
86
|
+
proof.iat !== signedContext.iat || proof.exp !== signedContext.exp)
|
|
87
|
+
throw new ArtifactContextError();
|
|
88
|
+
return Object.freeze({ authenticationMethod: proof.authenticationMethod, sub: proof.sub });
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
throw new ArtifactContextError();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -195,3 +195,4 @@ export declare function verifyArtifactRequestContext({ token, publicKeys, projec
|
|
|
195
195
|
export declare function getArtifactBrowserBootstrap(context: ArtifactRequestContext | RequestContextV2External): NextArtifactBridgeBootstrap & {
|
|
196
196
|
initialContext: NextArtifactInitialContext;
|
|
197
197
|
};
|
|
198
|
+
export { ARTIFACT_REQUEST_AUTHENTICATION_HEADER, verifyArtifactRequestAuthentication } from './request-authentication.js';
|
package/dist/server.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import 'server-only';
|
|
2
2
|
export { createArtifactServerClient } from './server/client.js';
|
|
3
|
+
export type { ArtifactServerAgents, ArtifactCompletedAgentRun, ArtifactCompletedAgentSourceCapture, ArtifactCompletedAgentConversationCapture, ArtifactAgentConversationSourceCapture, ArtifactExecutionIdentity, ArtifactCreateAgentJob, ArtifactCreateWorkflowJob, ArtifactCreatedAgentJob, ArtifactCreatedWorkflowJob, ArtifactCompletedWorkflowSourceCapture } from './server/agent-responses.js';
|
|
3
4
|
export { ArtifactPrincipalError, ArtifactServerError, INSUFFICIENT_USER_AUTHENTICATION, stepUpResponse } from './server/errors.js';
|
|
4
5
|
export type { ArtifactAtlasRefusal } from './server/errors.js';
|
|
5
|
-
export type { ArtifactAuditEvent, ArtifactOrmOperations, ArtifactOrmOptions, ArtifactProcessAdvance, ArtifactProcessAdvanceResult, ArtifactProcessArtifactRef, ArtifactProcessAssign, ArtifactProcessAssignResult, ArtifactProcessDefinition, ArtifactProcessDescribeQuery, ArtifactProcessEdge, ArtifactProcessHumanNode, ArtifactProcessNode, ArtifactProcessNodeBase, ArtifactProcessNodeState, ArtifactProcessPrincipal, ArtifactProcessPrincipalSearch, ArtifactProcessPrincipals, ArtifactProcessRun, ArtifactProcessRunRecord, ArtifactProcessRunSnapshot, ArtifactProcessRunSummary, ArtifactProcessRunsPage, ArtifactProcessRunsPageQuery, ArtifactProcessRunsQuery, ArtifactProcessRunViewerChange, ArtifactProcessRunViewers, ArtifactProcessStart, ArtifactProcessStepRecord, ArtifactProcessShareRun, ArtifactProcessShareRunResult, ArtifactProcessRunSharingAuthoritiesQuery, ArtifactProcessRunSharingAuthoritiesPage, ArtifactProcessRunSharingAuthority, ArtifactProcessRunSharingDelegate, ArtifactProcessRevokeRunSharingAuthority, ArtifactProcessRevokeRunSharingAuthorityResult, ArtifactProcessTask, ArtifactProcessTasksQuery, ArtifactServerAudit, ArtifactServerClient, ArtifactServerClientOptions, ArtifactServerContext, ArtifactServerFetchOptions, ArtifactServerFlags, ArtifactServerProcesses, } from './server/client.js';
|
|
6
|
-
export { ARTIFACT_AUDIT_ACTIONS, ARTIFACT_AUDIT_RESOURCES_PER_EVENT, ARTIFACT_FLAGS_PER_REQUEST, ARTIFACT_PROCESS_PRINCIPAL_SEARCH_LIMIT, ARTIFACT_PROCESS_PRINCIPAL_TYPES, ARTIFACT_PROCESS_PRINCIPALS_PER_CALL, ARTIFACT_PROCESS_RUN_STATUSES, ARTIFACT_PROCESS_RUNS_LIMIT, ARTIFACT_PROCESS_RUN_ENTITIES_LIMIT, ARTIFACT_PROCESS_SHARE_NODES_LIMIT, ARTIFACT_PROCESS_SHARING_AUTHORITIES_LIMIT, ARTIFACT_PROCESS_TASK_VIEWS, ARTIFACT_PROCESS_TASKS_LIMIT, } from './server/broker-contract.js';
|
|
6
|
+
export type { ArtifactAuditEvent, ArtifactOrmOperations, ArtifactOrmOptions, ArtifactProcessAdvance, ArtifactProcessAdvanceResult, ArtifactProcessArtifactRef, ArtifactProcessAssign, ArtifactProcessAssignResult, ArtifactProcessDefinition, ArtifactProcessDescribeQuery, ArtifactProcessEdge, ArtifactProcessHumanNode, ArtifactProcessNode, ArtifactProcessNodeBase, ArtifactProcessNodeState, ArtifactProcessPrincipal, ArtifactProcessPrincipalSearch, ArtifactProcessPrincipals, ArtifactProcessRun, ArtifactProcessRunRecord, ArtifactProcessRunSnapshot, ArtifactProcessRunSummary, ArtifactProcessRunsPage, ArtifactProcessRunsPageQuery, ArtifactProcessRunsQuery, ArtifactProcessRunViewerChange, ArtifactProcessRunViewers, ArtifactProcessStart, ArtifactProcessStepRecord, ArtifactProcessShareRun, ArtifactProcessShareRunResult, ArtifactProcessRunSharingAuthoritiesQuery, ArtifactProcessRunSharingAuthoritiesPage, ArtifactProcessRunSharingAuthority, ArtifactProcessRunSharingDelegate, ArtifactProcessRevokeRunSharingAuthority, ArtifactProcessRevokeRunSharingAuthorityResult, ArtifactProcessTask, ArtifactProcessTasksQuery, ArtifactServerAudit, ArtifactServerClient, ArtifactServerClientOptions, ArtifactServerContext, ArtifactServerFetchOptions, ArtifactServerFlags, ArtifactServerGroups, ArtifactServerProcesses, ArtifactGroupMembership, ArtifactGroupMembershipsPage, ArtifactGroupMembershipsQuery, } from './server/client.js';
|
|
7
|
+
export { ARTIFACT_AUDIT_ACTIONS, ARTIFACT_AUDIT_RESOURCES_PER_EVENT, ARTIFACT_FLAGS_PER_REQUEST, ARTIFACT_GROUP_MEMBERSHIPS_LIMIT, ARTIFACT_GROUP_MEMBERSHIPS_MAX_PAGE, ARTIFACT_PROCESS_PRINCIPAL_SEARCH_LIMIT, ARTIFACT_PROCESS_PRINCIPAL_TYPES, ARTIFACT_PROCESS_PRINCIPALS_PER_CALL, ARTIFACT_PROCESS_RUN_STATUSES, ARTIFACT_PROCESS_RUNS_LIMIT, ARTIFACT_PROCESS_RUN_ENTITIES_LIMIT, ARTIFACT_PROCESS_SHARE_NODES_LIMIT, ARTIFACT_PROCESS_SHARING_AUTHORITIES_LIMIT, ARTIFACT_PROCESS_TASK_VIEWS, ARTIFACT_PROCESS_TASKS_LIMIT, } from './server/broker-contract.js';
|
|
7
8
|
export type { ArtifactAuditAction, ArtifactProcessPrincipalType, ArtifactProcessRunStatus, ArtifactProcessTaskView, } from './server/broker-contract.js';
|
|
8
9
|
export { getArtifactRequestContext, readArtifactRuntimeConfig } from './server/runtime-config.js';
|
|
9
10
|
export type { ArtifactRuntimeConfig, ArtifactRequestHeaders } from './server/runtime-config.js';
|
|
10
|
-
export { ArtifactContextError, getArtifactBrowserBootstrap } from './server/request-context.js';
|
|
11
|
+
export { ArtifactContextError, getArtifactBrowserBootstrap, ARTIFACT_REQUEST_AUTHENTICATION_HEADER, verifyArtifactRequestAuthentication } from './server/request-context.js';
|
|
11
12
|
export type { ArtifactContextErrorReason, ArtifactRequestContext, RequestContextV2External } from './server/request-context.js';
|
|
12
13
|
export { verifyArtifactExternalContext } from './server/external-context.js';
|
|
13
14
|
export type { ArtifactExternalAccept } from './server/external-context.js';
|
package/dist/server.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import 'server-only';
|
|
2
2
|
export { createArtifactServerClient } from './server/client.js';
|
|
3
3
|
export { ArtifactPrincipalError, ArtifactServerError, INSUFFICIENT_USER_AUTHENTICATION, stepUpResponse } from './server/errors.js';
|
|
4
|
-
export { ARTIFACT_AUDIT_ACTIONS, ARTIFACT_AUDIT_RESOURCES_PER_EVENT, ARTIFACT_FLAGS_PER_REQUEST, ARTIFACT_PROCESS_PRINCIPAL_SEARCH_LIMIT, ARTIFACT_PROCESS_PRINCIPAL_TYPES, ARTIFACT_PROCESS_PRINCIPALS_PER_CALL, ARTIFACT_PROCESS_RUN_STATUSES, ARTIFACT_PROCESS_RUNS_LIMIT, ARTIFACT_PROCESS_RUN_ENTITIES_LIMIT, ARTIFACT_PROCESS_SHARE_NODES_LIMIT, ARTIFACT_PROCESS_SHARING_AUTHORITIES_LIMIT, ARTIFACT_PROCESS_TASK_VIEWS, ARTIFACT_PROCESS_TASKS_LIMIT, } from './server/broker-contract.js';
|
|
4
|
+
export { ARTIFACT_AUDIT_ACTIONS, ARTIFACT_AUDIT_RESOURCES_PER_EVENT, ARTIFACT_FLAGS_PER_REQUEST, ARTIFACT_GROUP_MEMBERSHIPS_LIMIT, ARTIFACT_GROUP_MEMBERSHIPS_MAX_PAGE, ARTIFACT_PROCESS_PRINCIPAL_SEARCH_LIMIT, ARTIFACT_PROCESS_PRINCIPAL_TYPES, ARTIFACT_PROCESS_PRINCIPALS_PER_CALL, ARTIFACT_PROCESS_RUN_STATUSES, ARTIFACT_PROCESS_RUNS_LIMIT, ARTIFACT_PROCESS_RUN_ENTITIES_LIMIT, ARTIFACT_PROCESS_SHARE_NODES_LIMIT, ARTIFACT_PROCESS_SHARING_AUTHORITIES_LIMIT, ARTIFACT_PROCESS_TASK_VIEWS, ARTIFACT_PROCESS_TASKS_LIMIT, } from './server/broker-contract.js';
|
|
5
5
|
export { getArtifactRequestContext, readArtifactRuntimeConfig } from './server/runtime-config.js';
|
|
6
|
-
export { ArtifactContextError, getArtifactBrowserBootstrap } from './server/request-context.js';
|
|
6
|
+
export { ArtifactContextError, getArtifactBrowserBootstrap, ARTIFACT_REQUEST_AUTHENTICATION_HEADER, verifyArtifactRequestAuthentication } from './server/request-context.js';
|
|
7
7
|
export { verifyArtifactExternalContext } from './server/external-context.js';
|
|
8
8
|
export { externalEvidence } from './server/principal.js';
|
package/dist/source-boundary.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { realpathSync } from 'node:fs';
|
|
1
2
|
import { isAbsolute, relative, resolve, sep } from 'node:path';
|
|
2
3
|
/**
|
|
3
4
|
* Artifact source must be self-contained: allowing a relative import to escape
|
|
@@ -7,8 +8,8 @@ import { isAbsolute, relative, resolve, sep } from 'node:path';
|
|
|
7
8
|
* allowed because they are external to the artifact by design.
|
|
8
9
|
*/
|
|
9
10
|
export function rejectOutsideSourcePlugin({ root, trustedExternalRoots, }) {
|
|
10
|
-
const rootResolved = resolve(root);
|
|
11
|
-
const trustedRoots = trustedExternalRoots.map((trustedRoot) => resolve(trustedRoot));
|
|
11
|
+
const rootResolved = realpathSync(resolve(root));
|
|
12
|
+
const trustedRoots = trustedExternalRoots.map((trustedRoot) => realpathSync(resolve(trustedRoot)));
|
|
12
13
|
return {
|
|
13
14
|
name: 'reject-artifact-outside-source',
|
|
14
15
|
enforce: 'pre',
|
|
@@ -17,15 +18,22 @@ export function rejectOutsideSourcePlugin({ root, trustedExternalRoots, }) {
|
|
|
17
18
|
if (!resolved || resolved.external || resolved.id.startsWith('\0'))
|
|
18
19
|
return resolved;
|
|
19
20
|
const filePath = resolved.id.split('?')[0];
|
|
20
|
-
if (!isAbsolute(filePath)
|
|
21
|
+
if (!isAbsolute(filePath))
|
|
22
|
+
return resolved;
|
|
23
|
+
// Vite may return a physical path for a root reached through /tmp or
|
|
24
|
+
// another symlink. Check physical paths on both sides of the boundary;
|
|
25
|
+
// this also prevents an in-root symlink from admitting an outside file.
|
|
26
|
+
const realFilePath = realpathSync(filePath);
|
|
27
|
+
if (isPathWithin(rootResolved, realFilePath))
|
|
21
28
|
return resolved;
|
|
22
29
|
const importerPath = importer?.split('?')[0];
|
|
23
30
|
const importerIsTrustedExternal = importerPath != null &&
|
|
24
|
-
(isNodeModulesPath(importerPath) ||
|
|
31
|
+
(isNodeModulesPath(importerPath) ||
|
|
32
|
+
(isAbsolute(importerPath) && isTrustedExternalPath(realpathSync(importerPath), trustedRoots)));
|
|
25
33
|
if (isNodeModulesPath(filePath) && (isBareImport(source) || importerIsTrustedExternal)) {
|
|
26
34
|
return resolved;
|
|
27
35
|
}
|
|
28
|
-
if (isTrustedExternalPath(
|
|
36
|
+
if (isTrustedExternalPath(realFilePath, trustedRoots))
|
|
29
37
|
return resolved;
|
|
30
38
|
const from = importer
|
|
31
39
|
? ` (imported from ${relative(rootResolved, importer.split('?')[0])})`
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {},
|
|
12
12
|
"devDependencies": {
|
|
13
|
-
"@sequenceholdings/artifact-studio": "^0.
|
|
13
|
+
"@sequenceholdings/artifact-studio": "^0.8.0",
|
|
14
14
|
"@sequenceholdings/atlas-ui": "^3.1.1",
|
|
15
15
|
"@tailwindcss/postcss": "^4.2.2",
|
|
16
16
|
"@tailwindcss/vite": "^4.2.2",
|
package/dist/tunnel/broker.d.ts
CHANGED
|
@@ -30,6 +30,8 @@ export interface GatewayAuthorization {
|
|
|
30
30
|
publicOrigin: string;
|
|
31
31
|
/** Signed, audience-scoped context minted by Atlas, never a user bearer. */
|
|
32
32
|
requestContext?: string;
|
|
33
|
+
/** Generated from the authenticated gateway session, never forwarded from a browser. */
|
|
34
|
+
requestAuthentication?: string;
|
|
33
35
|
}
|
|
34
36
|
export interface TunnelBrokerOptions {
|
|
35
37
|
nodeId: string;
|
|
@@ -52,6 +54,10 @@ export declare class ArtifactTunnelBroker {
|
|
|
52
54
|
private readonly pendingConnections;
|
|
53
55
|
private readonly ownerTimers;
|
|
54
56
|
private closing;
|
|
57
|
+
private draining;
|
|
58
|
+
private readonly drainWaiters;
|
|
59
|
+
private readonly pendingReceipts;
|
|
60
|
+
private relayClosed?;
|
|
55
61
|
constructor(options: TunnelBrokerOptions);
|
|
56
62
|
handleTunnelUpgrade(request: IncomingMessage, socket: Duplex, head: Buffer): Promise<void>;
|
|
57
63
|
handleHttp(request: IncomingMessage, response: ServerResponse, sessionId: string): Promise<void>;
|
|
@@ -59,6 +65,7 @@ export declare class ArtifactTunnelBroker {
|
|
|
59
65
|
handleExternalHttp(input: TunnelExternalRequest): Promise<void>;
|
|
60
66
|
handleWebSocketUpgrade(request: IncomingMessage, socket: Duplex, head: Buffer, sessionId: string): Promise<void>;
|
|
61
67
|
private authorize;
|
|
68
|
+
private requestHeaders;
|
|
62
69
|
/**
|
|
63
70
|
* The live tunnel for an external request: the session's current lease, for the granted project
|
|
64
71
|
* and environment, still valid. Null otherwise. No browser owner is compared: Atlas's grant
|
|
@@ -79,7 +86,13 @@ export declare class ArtifactTunnelBroker {
|
|
|
79
86
|
private writeExternalChunk;
|
|
80
87
|
private finish;
|
|
81
88
|
private abort;
|
|
82
|
-
/**
|
|
89
|
+
/** Stop new upgrades and remote-owner admission while admitted HTTP handlers finish. */
|
|
90
|
+
beginDrain(): void;
|
|
91
|
+
private notifyDrained;
|
|
92
|
+
/** The gateway first joins admitted handlers and response accounting. Its outer deadline
|
|
93
|
+
* bounds finite streams; lease validation and revocation remain active until cleanup. */
|
|
94
|
+
drain(): Promise<void>;
|
|
95
|
+
/** Immediate security revocation, never a graceful drain. */
|
|
83
96
|
disconnect(sessionId: string): void;
|
|
84
97
|
close(): void;
|
|
85
98
|
}
|